pax_global_header00006660000000000000000000000064147673543210014526gustar00rootroot0000000000000052 comment=bee742547c22ae43f35eae502c8ee25df0d0df66 libvmod-redis-21.0/000077500000000000000000000000001476735432100142105ustar00rootroot00000000000000libvmod-redis-21.0/.github/000077500000000000000000000000001476735432100155505ustar00rootroot00000000000000libvmod-redis-21.0/.github/workflows/000077500000000000000000000000001476735432100176055ustar00rootroot00000000000000libvmod-redis-21.0/.github/workflows/main.yml000066400000000000000000000045421476735432100212610ustar00rootroot00000000000000name: CI on: - push - pull_request jobs: test: runs-on: ubuntu-24.04 strategy: matrix: cc: - gcc - clang make_target: - check - distcheck configure_flags: - '' include: - cc: gcc make_target: lcov configure_flags: --enable-code-coverage steps: - uses: actions/checkout@v4 - name: Install packages run: | sudo apt update sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_SUSPEND=non-empty-value apt install -y \ automake autotools-dev lcov libedit-dev libev-dev \ libncurses-dev libpcre2-dev libssl-dev libtool python3-docutils \ python3-sphinx - name: Install Varnish Cache run: | wget --no-check-certificate https://varnish-cache.org/_downloads/varnish-7.7.0.tgz tar zxvf varnish-*.tgz pushd varnish-*/ ./autogen.sh CC='${{ matrix.cc }}' ./configure make -sj32 sudo make PREFIX='/usr/local' install sudo ldconfig popd - name: Install hiredis run: | wget --no-check-certificate https://github.com/redis/hiredis/archive/v1.2.0.zip -O hiredis-1.2.0.zip unzip hiredis-*.zip pushd hiredis-*/ make USE_SSL=1 sudo make USE_SSL=1 PREFIX='/usr/local' install sudo ldconfig popd - name: Install Redis run: | wget --no-check-certificate http://download.redis.io/releases/redis-7.4.1.tar.gz tar zxvf redis-*.tar.gz pushd redis-*/ make BUILD_TLS=yes sudo make BUILD_TLS=yes PREFIX='/usr/local' install sudo ldconfig popd - name: Build & test VMOD run: | ./autogen.sh CC='${{ matrix.cc }}' ./configure --prefix=/usr ${{ matrix.configure_flags }} make -j4 make ${{ matrix.make_target }} -j1 - name: Push code coverage if: ${{ matrix.make_target == 'lcov' }} run: | cp libvmod-redis-*-coverage.info codecov.info bash <(curl -s https://codecov.io/bash) -X gcov -X coveragepy -t ${{ secrets.CODECOV_TOKEN }} - name: Show test report if: ${{ failure() }} run: | cat src/test-suite.log || exit 0 libvmod-redis-21.0/.gitignore000066400000000000000000000005621476735432100162030ustar00rootroot00000000000000/.env Makefile Makefile.in .deps/ .libs/ *.o *.lo *.la *~ *.[1-9] *.log *.trs /aclocal.m4 /autom4te.cache/ /build-aux/ /config.h /config.h.in /config.log /config.status /configure /libtool /stamp-h1 /m4/libtool.m4 /m4/ltoptions.m4 /m4/ltsugar.m4 /m4/ltversion.m4 /m4/lt~obsolete.m4 /src/vcc_*_if.c /src/vcc_*_if.h /src/vmod_*rst /src/vmod_vcs_version.txt /.vagrant/ libvmod-redis-21.0/COPYING000066400000000000000000000002111476735432100152350ustar00rootroot00000000000000Copyright (c) 2014-2025 Carlos Abalde You're free to use and distribute this under terms in the LICENSE file. libvmod-redis-21.0/Dockerfile000066400000000000000000000034131476735432100162030ustar00rootroot00000000000000FROM ubuntu:noble-20250127 ENV DEBIAN_FRONTEND noninteractive RUN groupadd -g 5000 dev \ && useradd -u 5000 -g 5000 -m -s /bin/bash dev RUN apt update \ && apt install -y \ apt-transport-https \ automake \ autotools-dev \ bindfs \ binutils \ curl \ dpkg-dev \ git \ gpg \ graphviz \ jq \ less \ libedit-dev \ libev-dev \ libjemalloc-dev \ libncurses-dev \ libpcre2-dev \ libssl-dev \ libtool \ make \ nano \ netcat-traditional \ pkg-config \ python3 \ python3-docutils \ python3-sphinx \ python3-venv \ tar \ telnet \ unzip \ wget \ && apt clean \ && rm -rf /var/lib/apt/lists/* RUN cd /tmp \ && wget --no-check-certificate https://varnish-cache.org/_downloads/varnish-7.7.0.tgz \ && tar zxvf varnish-*.tgz \ && rm -f varnish-*.tgz \ && cd varnish-* \ && ./autogen.sh \ && ./configure \ && make \ && make PREFIX='/usr/local' install \ && ldconfig RUN cd /tmp \ && wget --no-check-certificate https://github.com/redis/hiredis/archive/v1.2.0.zip -O hiredis-1.2.0.zip \ && unzip hiredis-*.zip \ && rm -f hiredis-*.zip \ && cd hiredis* \ && make USE_SSL=1 \ && make USE_SSL=1 PREFIX='/usr/local' install \ && ldconfig RUN cd /tmp \ && wget --no-check-certificate http://download.redis.io/releases/redis-7.4.1.tar.gz \ && tar zxvf redis-*.tar.gz \ && rm -f redis-*.tar.gz \ && cd redis-* \ && make BUILD_TLS=yes \ && make BUILD_TLS=yes PREFIX='/usr/local' install \ && ldconfig COPY ./docker-entrypoint.sh / ENTRYPOINT ["/docker-entrypoint.sh"] libvmod-redis-21.0/LICENSE000066400000000000000000000024061476735432100152170ustar00rootroot00000000000000Copyright (c) 2014-2025 Carlos Abalde Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. libvmod-redis-21.0/Makefile.am000066400000000000000000000005761476735432100162540ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I m4 -I ${VARNISHAPI_DATAROOTDIR}/aclocal SUBDIRS = src dist_doc_DATA = README.rst LICENSE # lcov support CODE_COVERAGE_OUTPUT_DIRECTORY = lcov CODE_COVERAGE_IGNORE_PATTERN = "/usr/*" crc16.c sha1.c CODE_COVERAGE_LCOV_RMOPTS = --ignore-errors unused CODE_COVERAGE_GENHTML_OPTIONS = --prefix $(abs_top_srcdir) @CODE_COVERAGE_RULES@ lcov: check-code-coverage libvmod-redis-21.0/README.rst000066400000000000000000000246401476735432100157050ustar00rootroot00000000000000 .. image:: https://github.com/carlosabalde/libvmod-redis/actions/workflows/main.yml/badge.svg?branch=7.7 :alt: GitHub Actions CI badge :target: https://github.com/carlosabalde/libvmod-redis/actions .. image:: https://codecov.io/gh/carlosabalde/libvmod-redis/branch/7.7/graph/badge.svg :alt: Codecov badge :target: https://codecov.io/gh/carlosabalde/libvmod-redis VMOD using the `synchronous hiredis library API `_ to access Redis servers from VCL. For an alternative using libvalkey + Valkey, please check the `libvmod-valkey VMOD `_ project. Highlights: * **Full support for execution of LUA scripts** (i.e. ``EVAL`` command), including optimistic automatic execution of ``EVALSHA`` commands. * **All Redis reply data types are supported**, including partial support to access to components of simple (i.e. not nested) array replies. * **Redis pipelines are not (and won't be) supported**. LUA scripting, which is fully supported by the VMOD, it's a much more flexible alternative to pipelines for atomic execution and minimizing latency. Pipelines are hard to use and error prone, specially when using the ``WATCH`` command. * **Support for classic Redis deployments** using multiple replicated Redis servers **and for clustered deployments based on Redis Cluster**. * **Support for multiple databases and multiple Redis connections**, local to each Varnish worker thread, or shared using one or more pools. * **Support for smart command execution**, selecting the destination server according with the preferred role (i.e. master or slave) and with distance and healthiness metrics collected during execution. * **Support for Redis Sentinel**, allowing automatic discovery of sick / healthy servers and changes in their roles. Please, check out `the project wiki `_ for some extra information and useful links. Looking for official support for this VMOD? Please, contact `Allenta Consulting `_, a `Varnish Software Premium partner `_. SYNOPSIS ======== import redis; :: ## ## Subnets. ## Function subnets(STRING masks="") ## ## Sentinels. ## Function sentinels( STRING locations="", INT period=60, INT connection_timeout=500, INT command_timeout=0, ENUM { RESP2, RESP3, default } protocol="default", BOOL tls=false, STRING tls_cafile="", STRING tls_capath="", STRING tls_certfile="", STRING tls_keyfile="", STRING tls_sni="", STRING password="") ## ## Proxy. ## # Instance selection. Function VOID use(STRING db) # Proxied methods. Method VOID .add_server(..., STRING db="") Function VOID command(..., STRING db="") Function VOID timeout(..., STRING db="") Function VOID retries(..., STRING db="") ... Method STRING .stats(..., STRING db="") Method INT .counter(..., STRING db="") ## ## Databases. ## # Constructor. Object db( STRING location="", ENUM { master, slave, auto, cluster } type="auto", INT connection_timeout=1000, INT connection_ttl=0, INT command_timeout=0, INT max_command_retries=0, BOOL shared_connections=true, INT max_connections=128, ENUM { RESP2, RESP3, default } protocol="default", BOOL tls=false, STRING tls_cafile="", STRING tls_capath="", STRING tls_certfile="", STRING tls_keyfile="", STRING tls_sni="", STRING user="", STRING password="", INT sickness_ttl=60, BOOL ignore_slaves=false, INT max_cluster_hops=32) Method VOID .add_server( STRING location, ENUM { master, slave, auto, cluster } type) # Command execution. Method VOID .command(STRING name) Method VOID .timeout(INT command_timeout) Method VOID .retries(INT max_command_retries) Method VOID .push(STRING arg) Method VOID .execute(BOOL master=true) Method VOID .easy_execute(STRING command, [STRING command_args...], BOOL master=true, INT command_timeout, INT max_command_retries) # Access to replies. Method BOOL .replied() Method BOOL .reply_is_error() Method BOOL .reply_is_nil() Method BOOL .reply_is_status() Method BOOL .reply_is_integer() Method BOOL .reply_is_boolean() Method BOOL .reply_is_double() Method BOOL .reply_is_string() Method BOOL .reply_is_array() Method STRING .get_reply() Method STRING .get_error_reply() Method STRING .get_status_reply() Method INT .get_integer_reply() Method BOOL .get_boolean_reply() Method REAL .get_double_reply() Method STRING .get_string_reply() Method INT .get_array_reply_length() Method BOOL .array_reply_is_error(INT index) Method BOOL .array_reply_is_nil(INT index) Method BOOL .array_reply_is_status(INT index) Method BOOL .array_reply_is_integer(INT index) Method BOOL .array_reply_is_boolean(INT index) Method BOOL .array_reply_is_double(INT index) Method BOOL .array_reply_is_string(INT index) Method BOOL .array_reply_is_array(INT index) Method STRING .get_array_reply_value(INT index) # Other. Method VOID .free() Method STRING .stats( ENUM { json, prometheus } format="json", BOOL stream=0, STRING prometheus_name_prefix="vmod_redis_", BOOL prometheus_default_labels=1, STRING prometheus_extra_labels="") Method INT .counter(STRING name) EXAMPLES ======== Single server ------------- :: sub vcl_init { # VMOD configuration: simple case, keeping up to one Redis connection # per Varnish worker thread. new db = redis.db( location="192.168.1.100:6379", type=master, connection_timeout=500, shared_connections=false, max_connections=1); } sub vcl_deliver { # Simple command execution. db.command("SET"); db.push("foo"); db.push("Hello world!"); db.execute(); # Alternatively, the same can be achieved with one single command db.easy_execute("SET", "foo", "Hello world!"); # LUA scripting. db.command("EVAL"); db.push({" redis.call('SET', KEYS[1], ARGV[1]) redis.call('SET', KEYS[2], ARGV[1]) "}); db.push("2"); db.push("foo"); db.push("bar"); db.push("Atomic hello world!"); db.execute(); # Array replies, checking & accessing to reply. db.command("MGET"); db.push("foo"); db.push("bar"); db.execute(); if ((db.reply_is_array()) && (db.get_array_reply_length() == 2)) { set resp.http.X-Foo = db.get_array_reply_value(0); set resp.http.X-Bar = db.get_array_reply_value(1); } } Multiple servers ---------------- :: sub vcl_init { # VMOD configuration: master-slave replication, keeping up to two # Redis connections per Varnish worker thread (up to one to the master # server & up to one to the closest slave server). redis.subnets( masks={" 0 192.168.1.102/32, 1 192.168.1.103/32, 2 0.0.0.0/32 "}); new db = redis.db( location="192.168.1.100:6379", type=master, connection_timeout=500, shared_connections=false, max_connections=2); db.add_server("192.168.1.101:6379", slave); db.add_server("192.168.1.102:6379", slave); db.add_server("192.168.1.103:6379", slave); } sub vcl_deliver { # SET submitted to the master server. db.command("SET"); db.push("foo"); db.push("Hello world!"); db.execute(); # GET submitted to one of the slave servers. db.command("GET"); db.push("foo"); db.execute(false); set req.http.X-Foo = db.get_string_reply(); } Clustered setup --------------- :: sub vcl_init { # VMOD configuration: clustered setup, keeping up to 100 Redis # connections per server, all shared between all Varnish worker threads. # Two initial cluster servers are provided; remaining servers are # automatically discovered. new db = redis.db( location="192.168.1.100:6379", type=cluster, connection_timeout=500, shared_connections=true, max_connections=128, max_cluster_hops=16); db.add_server("192.168.1.101:6379", cluster); } sub vcl_deliver { # SET internally routed to the destination server. db.command("SET"); db.push("foo"); db.push("Hello world!"); db.execute(); # GET internally routed to the destination server. db.command("GET"); db.push("foo"); db.execute(false); set req.http.X-Foo = db.get_string_reply(); } INSTALLATION ============ The source tree is based on autotools to configure the building, and does also have the necessary bits in place to do functional unit tests using the varnishtest tool. **Beware this project contains multiples branches (master, 4.1, 4.0, etc.). Please, select the branch to be used depending on your Varnish Cache version (Varnish trunk → master, Varnish 4.1.x → 4.1, Varnish 4.0.x → 4.0, etc.).** Dependencies: * `hiredis `_ - minimalistic C Redis client library. * `libev `_ - full-featured and high-performance event loop. COPYRIGHT ========= See LICENSE for details. Public domain implementation of the SHA-1 cryptographic hash function by Steve Reid and embedded in this VMOD (required for the optimistic execution of ``EVALSHA`` commands) has been borrowed from `this project `_: * https://github.com/clibs/sha1/blob/master/sha1.c * https://github.com/clibs/sha1/blob/master/sha1.h BSD's implementation of the CRC-16 cryptographic hash function by Georges Menie & Salvatore Sanfilippo and embedded in this VMOD (required for the Redis Cluster slot calculation) has been borrowed from the `Redis project `_: * http://download.redis.io/redis-stable/src/crc16.c Copyright (c) Carlos Abalde libvmod-redis-21.0/autogen.sh000077500000000000000000000020721476735432100162120ustar00rootroot00000000000000#!/bin/sh warn() { echo "WARNING: $@" 1>&2 } case `uname -s` in Darwin) LIBTOOLIZE=glibtoolize ;; FreeBSD) LIBTOOLIZE=libtoolize ;; Linux) LIBTOOLIZE=libtoolize ;; SunOS) LIBTOOLIZE=libtoolize ;; *) warn "unrecognized platform:" `uname -s` LIBTOOLIZE=libtoolize esac automake_version=`automake --version | tr ' ' '\n' | egrep '^[0-9]\.[0-9a-z.-]+'` if [ -z "$automake_version" ] ; then warn "unable to determine automake version" else case $automake_version in 0.*|1.[0-8]|1.[0-8][.-]*) warn "automake ($automake_version) detected; 1.9 or newer recommended" ;; *) ;; esac fi # check for varnishapi.m4 in custom paths dataroot=$(pkg-config --variable=datarootdir varnishapi 2>/dev/null) if [ -z "$dataroot" ] ; then cat >&2 <<'EOF' Package varnishapi was not found in the pkg-config search path. Perhaps you should add the directory containing `varnishapi.pc' to the PKG_CONFIG_PATH environment variable EOF exit 1 fi set -ex aclocal -I m4 -I ${dataroot}/aclocal $LIBTOOLIZE --copy --force autoheader automake --add-missing --copy --foreign autoconf libvmod-redis-21.0/configure.ac000066400000000000000000000047011476735432100165000ustar00rootroot00000000000000AC_PREREQ([2.68]) AC_INIT([libvmod-redis], [21.0], [], [vmod-redis]) AC_COPYRIGHT([Copyright (c) Carlos Abalde ]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_SRCDIR(src/vmod_redis.vcc) AC_CONFIG_HEADER([config.h]) AC_GNU_SOURCE AM_INIT_AUTOMAKE([1.12 -Wall -Werror foreign parallel-tests]) AM_SILENT_RULES([yes]) AM_PROG_AR LT_PREREQ([2.2.6]) LT_INIT([dlopen disable-static]) ax_enable_compile_warnings=error AX_CODE_COVERAGE AX_COMPILER_FLAGS_CFLAGS AX_PTHREAD(,[AC_MSG_ERROR([Could not configure pthreads support])]) LIBS="$PTHREAD_LIBS $LIBS -lhiredis -lev" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" CC="$PTHREAD_CC" AC_ARG_WITH([rst2man], [ AS_HELP_STRING( [--with-rst2man=PATH], [Location of rst2man (auto)]) ], [RST2MAN="$withval"], [AC_CHECK_PROGS(RST2MAN, [rst2man rst2man.py], [])]) m4_ifndef([VARNISH_PREREQ], AC_MSG_ERROR([Need varnish.m4 -- see README.rst])) VARNISH_PREREQ([7.7], [7.8]) VARNISH_VMODS([redis]) VMOD_TESTS="$(cd $srcdir/src && echo tests/*.vtc)" AC_SUBST(VMOD_TESTS) PKG_CHECK_VAR([LIBVARNISHAPI_LIBDIR], [varnishapi], [libdir]) AC_SUBST([VARNISH_LIBRARY_PATH], [$LIBVARNISHAPI_LIBDIR:$LIBVARNISHAPI_LIBDIR/varnish]) # Check for libhiredis. AC_CHECK_LIB( hiredis, redisCommand, [], [AC_MSG_ERROR([libvmod-redis requires libhiredis.])]) # Check for libev3 (ev_loop) / libev4 (ev_run). # -DEV_COMPAT3=1 used during build. AC_CHECK_LIB( ev, ev_loop, [], [AC_CHECK_LIB( ev, ev_run, [], [AC_MSG_ERROR([libvmod-redis requires libev.])])]) # Check for TLS support: --enable-tls / --disable-tls AC_ARG_ENABLE( tls, [ AS_HELP_STRING( [--enable-tls], [enable TLS support (default is YES)]) ], [], [enable_tls=yes]) AC_MSG_CHECKING([for TLS support]) if test "x$enable_tls" = xyes; then AC_MSG_RESULT([enabled]) AC_DEFINE( [TLS_ENABLED], [1], [TLS enabled]) AC_CHECK_LIB( crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([libvmod-redis requires libcrypto. Try --disable-tls.])]) AC_CHECK_LIB( ssl, SSL_CTX_new, [], [AC_MSG_ERROR([libvmod-redis requires libssl. Try --disable-tls.])]) AC_CHECK_LIB( hiredis_ssl, redisInitiateSSL, [], [AC_MSG_ERROR([libvmod-redis requires libhiredis_ssl. Try --disable-tls.])]) AC_CHECK_LIB( varnish-sslhelper, VSSLH_status, [], []) else AC_MSG_RESULT([disabled]) fi AC_CONFIG_FILES([ Makefile src/Makefile ]) AC_OUTPUT libvmod-redis-21.0/debian/000077500000000000000000000000001476735432100154325ustar00rootroot00000000000000libvmod-redis-21.0/debian/changelog000066400000000000000000000256561476735432100173220ustar00rootroot00000000000000libvmod-redis (21.0-1) stable; urgency=low * Migrated to Varnish Cache 7.7.x -- Carlos Abalde Tue, 18 Mar 2025 16:00:00 +0100 libvmod-redis (20.0-1) stable; urgency=low * Migrated to Varnish Cache 7.6.x -- Carlos Abalde Fri, 13 Sep 2024 16:00:00 +0200 libvmod-redis (19.0-1) stable; urgency=low * Migrated to Varnish Cache 7.5.x -- Carlos Abalde Tue, 19 Mar 2024 16:00:00 +0100 libvmod-redis (18.0-1) stable; urgency=low * Migrated to Varnish Cache 7.4.x -- Carlos Abalde Fri, 15 Sep 2023 16:00:00 +0200 libvmod-redis (17.1-1) stable; urgency=low * Fixed a couple of Redis Cluster & Redis Sentinel IPv6 issues. * Fixed build under FreeBSD. * Added some missing AN() & AZ(). * Introduced '.easy_execute()'. * Fixed potential segmentation fault due to wrong logging in Sentinel thread. -- Carlos Abalde Fri, 28 Apr 2023 16:00:00 +0200 libvmod-redis (17.0-1) stable; urgency=low * Migrated to Varnish Cache 7.3.x -- Carlos Abalde Wed, 15 Mar 2023 16:00:00 +0100 libvmod-redis (16.0-1) stable; urgency=low * Migrated to Varnish Cache 7.2.x -- Carlos Abalde Thu, 15 Sep 2022 16:00:00 +0200 libvmod-redis (15.1-1) stable; urgency=low * Fixed missing string terminator in .stats() method -- Carlos Abalde Thu, 02 Jun 2022 16:00:00 +0200 libvmod-redis (15.0-1) stable; urgency=low * Migrated to Varnish Cache 7.1.x -- Carlos Abalde Tue, 15 Mar 2022 16:00:00 +0100 libvmod-redis (14.1-1) stable; urgency=low * Added support for streaming & Prometheus format to the .stats() method * Added CHECK_OBJ_NOTNULL() checks in all free_*() functions -- Carlos Abalde Wed, 12 Jan 2022 16:00:00 +0100 libvmod-redis (14.0-1) stable; urgency=low * Migrated to Varnish Cache 7.0.x -- Carlos Abalde Wed, 15 Sep 2021 16:00:00 +0200 libvmod-redis (13.0-1) stable; urgency=low * Migrated to Varnish Cache 6.6.x -- Carlos Abalde Mon, 15 Mar 2021 16:00:00 +0100 libvmod-redis (12.0-1) stable; urgency=low * Migrated to Varnish Cache 6.5.x -- Carlos Abalde Tue, 15 Sep 2020 16:00:00 +0200 libvmod-redis (11.1-1) stable; urgency=low * Added support for larger integers * Added support for Redis ACLs * Fixed wrong error message when successfully authenticating Sentinel connections * Fixed 'SENTINEL masters' execution: send AUTH if password is available * Improved logging * Added RESP3 support (depends on future hiredis >= 1.0) * Added TLS support (depends on future hiredis >= 1.0) -- Carlos Abalde Fri, 17 Jul 2020 16:00:00 +0200 libvmod-redis (11.0-1) stable; urgency=low * Migrated to Varnish Cache 6.4.x -- Carlos Abalde Fri, 20 Mar 2020 16:00:00 +0100 libvmod-redis (10.1-1) stable; urgency=low * Added support for Redis Sentinel authentication * Added Linux Alpine fixes -- Carlos Abalde Fri, 21 Feb 2020 16:00:00 +0100 libvmod-redis (10.0-1) stable; urgency=low * Migrated to Varnish Cache 6.3.x -- Carlos Abalde Mon, 30 Sep 2019 16:00:00 +0200 libvmod-redis (9.1-1) stable; urgency=low * Stopped depending on redis-trib.rb * Added REPLICAOF command (i.e. new SLAVEOF name) support -- Carlos Abalde Thu, 23 May 2019 17:00:00 +0200 libvmod-redis (9.0-1) stable; urgency=low * Migrated to Varnish Cache 6.2.x -- Carlos Abalde Mon, 18 Mar 2019 16:00:00 +0100 libvmod-redis (8.0-1) stable; urgency=low * Migrated to Varnish Cache 6.1.x -- Carlos Abalde Tue, 18 Sep 2018 16:00:00 +0200 libvmod-redis (7.2-1) stable; urgency=low * Allowed disabling sickness TTL feature * Stopped WS-copying input arg in .command() & .push() -- Carlos Abalde Tue, 07 Aug 2018 17:00:00 +0200 libvmod-redis (7.1-1) stable; urgency=low * Fixed execution plan when clustering enabled -- Carlos Abalde Thu, 03 May 2018 17:00:00 +0200 libvmod-redis (7.0-1) stable; urgency=low * Migrated to Varnish Cache 6.0.x -- Carlos Abalde Thu, 15 Mar 2018 16:00:00 +0100 libvmod-redis (6.0-1) stable; urgency=low * Migrated to Varnish Cache 5.2.x -- Carlos Abalde Fri, 15 Sep 2017 16:00:00 +0200 libvmod-redis (5.1-1) stable; urgency=low * Added proxied methods -- Carlos Abalde Thu, 01 Jun 2017 17:00:00 +0200 libvmod-redis (5.0-1) stable; urgency=low * Migrated to Varnish Cache 5.1.x -- Carlos Abalde Fri, 17 Mar 2017 16:00:00 +0100 libvmod-redis (4.0-1) stable; urgency=low * Migrated to Varnish Cache 5.0.x -- Carlos Abalde Fri, 17 Mar 2017 16:00:00 +0100 libvmod-redis (3.11-1) stable; urgency=low * Added 'ignore_slaves' option to redis.db() -- Carlos Abalde Wed, 26 Oct 2016 17:00:00 +0200 libvmod-redis (3.10-1) stable; urgency=low * Fixed Sentinel-related crash -- Carlos Abalde Thu, 04 Aug 2016 17:00:00 +0200 libvmod-redis (3.9-1) stable; urgency=low * Added full password support when clustering is enabled -- Carlos Abalde Wed, 03 Aug 2016 17:00:00 +0200 libvmod-redis (3.8-1) stable; urgency=low * Fixed crash when destroying ev loops -- Carlos Abalde Thu, 14 Jul 2016 17:00:00 +0200 libvmod-redis (3.7-1) stable; urgency=low * Fixed shared ev loop -- Carlos Abalde Wed, 13 Jul 2016 17:00:00 +0200 libvmod-redis (3.6-1) stable; urgency=low * Allowed server-less database instantiation -- Carlos Abalde Mon, 11 Jul 2016 17:00:00 +0200 libvmod-redis (3.5-1) stable; urgency=low * Avoided deadlocks enforcing lock ordering + simplifying locking model -- Carlos Abalde Thu, 09 Jun 2016 17:00:00 +0200 libvmod-redis (3.4-1) stable; urgency=low * Stop assuming down flag on +switch-master events -- Carlos Abalde Mon, 02 May 2016 17:00:00 +0200 libvmod-redis (3.3-1) stable; urgency=low * Added Redis Sentinel support * Added support for auto-discovery of roles * Replaced plain pthread mutexes by Varnish locks * Dynamic allocation of execution plans * Improved logging * Added redis.subnets() (previosuly redis.init()) * Improvements & fixes -- Carlos Abalde Wed, 20 Apr 2016 17:00:00 +0200 libvmod-redis (3.2-1) stable; urgency=low * Improvements & fixes -- Carlos Abalde Tue, 12 Apr 2016 17:00:00 +0200 libvmod-redis (3.1-1) stable; urgency=low * Added support for smart command execution * Added redis.init(), including weights + subnet masks * Added type (master, slave, cluster) and sickness TTL to redis.db() * Added master / slave selection to .execute() * Improvements & fixes -- Carlos Abalde Mon, 11 Apr 2016 17:00:00 +0200 libvmod-redis (3.0-1) stable; urgency=low * New version numbering scheme -- Carlos Abalde Mon, 04 Apr 2016 17:00:00 +0200 libvmod-redis (0.3.6-1) stable; urgency=low * Improved VSL / syslog logging -- Carlos Abalde Mon, 29 Feb 2016 17:00:00 +0100 libvmod-redis (0.3.5-1) stable; urgency=low * Added AUTH support -- Carlos Abalde Tue, 09 Feb 2016 17:00:00 +0100 libvmod-redis (0.3.4-1) stable; urgency=low * Added .counter() * Improved handling of -MOVED errors * Simplified & improved internals -- Carlos Abalde Tue, 22 Dec 2015 17:00:00 +0100 libvmod-redis (0.3.3-1) stable; urgency=low * Improvements & fixes -- Carlos Abalde Tue, 22 Dec 2015 16:00:00 +0100 libvmod-redis (0.3.2-1) stable; urgency=low * Added .stats() -- Carlos Abalde Mon, 21 Dec 2015 16:00:00 +0100 libvmod-redis (0.3.1-1) stable; urgency=low * Removed support for server tags * Removed .add_cserver() * Removed .server() -- Carlos Abalde Wed, 16 Dec 2015 16:00:00 +0100 libvmod-redis (0.3.0-1) stable; urgency=low * Added support for multiple clusters * Added .retries() * Removed redis.fini() * Improved manual page -- Carlos Abalde Tue, 15 Dec 2015 16:00:00 +0100 libvmod-redis (0.2.7-1) stable; urgency=low * Fixed memory leak during redis.fini() * Fixed initialization / reset of command execution timeout * Added Redis Cluster tests -- Carlos Abalde Mon, 08 Jun 2015 16:00:00 +0200 libvmod-redis (0.2.6-1) stable; urgency=low * Fixed bug when processing -MOVED and -ASK errors * Updated files borrowed from the Redis implementation -- Carlos Abalde Tue, 26 May 2015 16:00:00 +0200 libvmod-redis (0.2.5-1) stable; urgency=low * Do not require C99 standard -- Carlos Abalde Tue, 12 May 2015 16:00:00 +0200 libvmod-redis (0.2.4-1) stable; urgency=low * Added support for timeouts when executing commands * Maximum number of Redis Cluster hops is now configurable -- Carlos Abalde Fri, 17 Apr 2015 16:00:00 +0200 libvmod-redis (0.2.3-1) stable; urgency=low * Added support for hiredis 0.12.1 (redisEnableKeepAlive) * Updated Redis Cluster key -> slot calculation -- Carlos Abalde Wed, 28 Jan 2015 16:00:00 +0200 libvmod-redis (0.2.2-1) stable; urgency=low * Added support for command retries -- Carlos Abalde Fri, 19 Dec 2014 16:00:00 +0200 libvmod-redis (0.2.1-1) stable; urgency=low * Added redis.replied() * Minor fixes -- Carlos Abalde Wed, 17 Dec 2014 16:00:00 +0200 libvmod-redis (0.2.0-1) stable; urgency=low * Added Redis Cluster support * Minor improvements & fixes -- Carlos Abalde Tue, 16 Dec 2014 16:00:00 +0200 libvmod-redis (0.1.3-1) stable; urgency=low * Added support for shared pools of Redis connections * Refactor to simplify future support of Redis Cluster -- Carlos Abalde Sun, 14 Dec 2014 16:00:00 +0200 libvmod-redis (0.1.2-1) stable; urgency=low * Discard Redis contexts when connections are hung up by the server -- Carlos Abalde Thu, 23 Oct 2014 16:00:00 +0200 libvmod-redis (0.1.1-1) stable; urgency=low * Added missing WS_Dup()'s / WS_Copy()'s -- Carlos Abalde Wed, 17 Sep 2014 16:00:00 +0200 libvmod-redis (0.1.0-1) stable; urgency=low * Initial version -- Carlos Abalde Fri, 22 Aug 2014 16:00:00 +0200 libvmod-redis-21.0/debian/compat000066400000000000000000000000021476735432100166300ustar00rootroot000000000000007 libvmod-redis-21.0/debian/control000066400000000000000000000010641476735432100170360ustar00rootroot00000000000000Source: libvmod-redis Section: web Priority: extra Maintainer: Carlos Abalde Build-Depends: debhelper (>= 7), build-essential, pkg-config, python-docutils | python3-docutils, varnish (>= 7.7.0), libvarnishapi-dev (>= 7.7.0), libhiredis-dev (>= 0.11.0), libev-dev (>= 4.15) Standards-Version: 3.8.1 Package: libvmod-redis Architecture: any Depends: varnish (>= 7.7.0), libhiredis0.10 (>= 0.11.0) | libhiredis0.13 (>= 0.13.3), libev4 (>= 4.15), ${shlibs:Depends}, ${misc:Depends}, ${Varnish:ABI} Description: Redis VMOD for Varnish libvmod-redis-21.0/debian/copyright000066400000000000000000000001731476735432100173660ustar00rootroot00000000000000Copyright: Copyright Carlos Abalde License: You're free to use and distribute this under terms in the LICENSE file. libvmod-redis-21.0/debian/dirs000066400000000000000000000000341476735432100163130ustar00rootroot00000000000000usr/share/doc/libvmod-redis libvmod-redis-21.0/debian/docs000066400000000000000000000000231476735432100163000ustar00rootroot00000000000000README.rst LICENSE libvmod-redis-21.0/debian/rules000077500000000000000000000003321476735432100165100ustar00rootroot00000000000000#!/usr/bin/make -f export DH_VERBOSE=1 override_dh_gencontrol: if [ -n "$$DEBIAN_OVERRIDE_BINARY_VERSION" ]; then \ dh_gencontrol -- -v$$DEBIAN_OVERRIDE_BINARY_VERSION; \ else \ dh_gencontrol ; \ fi %: dh $@ libvmod-redis-21.0/docker-compose.yml000066400000000000000000000011501476735432100176420ustar00rootroot00000000000000--- # # Cheat sheet: # $ echo -e "UID=$(id -u)\nGID=$(id -g)" > .env # $ docker compose up --build --detach # $ docker compose exec --user dev --workdir /mnt/host dev bash # $ ./autogen.sh # $ ./configure # $ make # $ make check # $ docker compose down --volumes --remove-orphans # version: '3.7' name: libvmod-redis-7_7 services: dev: hostname: dev build: context: . privileged: true environment: HOST_UID: ${UID:?} HOST_GID: ${GID:?} volumes: - .:/mnt/host.raw tmpfs: - /run - /run/lock - /var/cache - /tmp:exec libvmod-redis-21.0/docker-entrypoint.sh000077500000000000000000000005111476735432100202240ustar00rootroot00000000000000#!/usr/bin/env bash mkdir -p /mnt/host # Beware 'privileged: true' is required for this. bindfs \ --force-user=$(id -u dev) \ --force-group=$(id -g dev) \ --create-for-user=$HOST_UID \ --create-for-group=$HOST_GID \ --chown-ignore \ --chgrp-ignore \ /mnt/host.raw \ /mnt/host tail -f /dev/null libvmod-redis-21.0/m4/000077500000000000000000000000001476735432100145305ustar00rootroot00000000000000libvmod-redis-21.0/m4/ax_code_coverage.m4000066400000000000000000000270731476735432100202600ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_code_coverage.html # =========================================================================== # # SYNOPSIS # # AX_CODE_COVERAGE() # # DESCRIPTION # # Defines CODE_COVERAGE_CPPFLAGS, CODE_COVERAGE_CFLAGS, # CODE_COVERAGE_CXXFLAGS and CODE_COVERAGE_LIBS which should be included # in the CPPFLAGS, CFLAGS CXXFLAGS and LIBS/LIBADD variables of every # build target (program or library) which should be built with code # coverage support. Also defines CODE_COVERAGE_RULES which should be # substituted in your Makefile; and $enable_code_coverage which can be # used in subsequent configure output. CODE_COVERAGE_ENABLED is defined # and substituted, and corresponds to the value of the # --enable-code-coverage option, which defaults to being disabled. # # Test also for gcov program and create GCOV variable that could be # substituted. # # Note that all optimisation flags in CFLAGS must be disabled when code # coverage is enabled. # # Usage example: # # configure.ac: # # AX_CODE_COVERAGE # # Makefile.am: # # @CODE_COVERAGE_RULES@ # my_program_LIBS = ... $(CODE_COVERAGE_LIBS) ... # my_program_CPPFLAGS = ... $(CODE_COVERAGE_CPPFLAGS) ... # my_program_CFLAGS = ... $(CODE_COVERAGE_CFLAGS) ... # my_program_CXXFLAGS = ... $(CODE_COVERAGE_CXXFLAGS) ... # # This results in a "check-code-coverage" rule being added to any # Makefile.am which includes "@CODE_COVERAGE_RULES@" (assuming the module # has been configured with --enable-code-coverage). Running `make # check-code-coverage` in that directory will run the module's test suite # (`make check`) and build a code coverage report detailing the code which # was touched, then print the URI for the report. # # In earlier versions of this macro, CODE_COVERAGE_LDFLAGS was defined # instead of CODE_COVERAGE_LIBS. They are both still defined, but use of # CODE_COVERAGE_LIBS is preferred for clarity; CODE_COVERAGE_LDFLAGS is # deprecated. They have the same value. # # This code was derived from Makefile.decl in GLib, originally licenced # under LGPLv2.1+. # # LICENSE # # Copyright (c) 2012, 2016 Philip Withnall # Copyright (c) 2012 Xan Lopez # Copyright (c) 2012 Christian Persch # Copyright (c) 2012 Paolo Borelli # Copyright (c) 2012 Dan Winship # Copyright (c) 2015 Bastien ROUCARIES # # This library is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or (at # your option) any later version. # # This library is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . #serial 20 AC_DEFUN([AX_CODE_COVERAGE],[ dnl Check for --enable-code-coverage AC_REQUIRE([AC_PROG_SED]) # allow to override gcov location AC_ARG_WITH([gcov], [AS_HELP_STRING([--with-gcov[=GCOV]], [use given GCOV for coverage (GCOV=gcov).])], [_AX_CODE_COVERAGE_GCOV_PROG_WITH=$with_gcov], [_AX_CODE_COVERAGE_GCOV_PROG_WITH=gcov]) AC_MSG_CHECKING([whether to build with code coverage support]) AC_ARG_ENABLE([code-coverage], AS_HELP_STRING([--enable-code-coverage], [Whether to enable code coverage support]),, enable_code_coverage=no) AM_CONDITIONAL([CODE_COVERAGE_ENABLED], [test x$enable_code_coverage = xyes]) AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage]) AC_MSG_RESULT($enable_code_coverage) AS_IF([ test "$enable_code_coverage" = "yes" ], [ # check for gcov AC_CHECK_TOOL([GCOV], [$_AX_CODE_COVERAGE_GCOV_PROG_WITH], [:]) AS_IF([test "X$GCOV" = "X:"], [AC_MSG_ERROR([gcov is needed to do coverage])]) AC_SUBST([GCOV]) dnl Check if gcc is being used AS_IF([ test "$GCC" = "no" ], [ AC_MSG_ERROR([not compiling with gcc, which is required for gcov code coverage]) ]) AC_CHECK_PROG([LCOV], [lcov], [lcov]) AC_CHECK_PROG([GENHTML], [genhtml], [genhtml]) AS_IF([ test -z "$LCOV" ], [ AC_MSG_ERROR([To enable code coverage reporting you must have lcov installed]) ]) AS_IF([ test -z "$GENHTML" ], [ AC_MSG_ERROR([Could not find genhtml from the lcov package]) ]) dnl Build the code coverage flags dnl Define CODE_COVERAGE_LDFLAGS for backwards compatibility CODE_COVERAGE_CPPFLAGS="-DNDEBUG" CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" CODE_COVERAGE_CXXFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" CODE_COVERAGE_LIBS="-lgcov" CODE_COVERAGE_LDFLAGS="$CODE_COVERAGE_LIBS" AC_SUBST([CODE_COVERAGE_CPPFLAGS]) AC_SUBST([CODE_COVERAGE_CFLAGS]) AC_SUBST([CODE_COVERAGE_CXXFLAGS]) AC_SUBST([CODE_COVERAGE_LIBS]) AC_SUBST([CODE_COVERAGE_LDFLAGS]) [CODE_COVERAGE_RULES_CHECK=' -$(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k check $(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) code-coverage-capture '] [CODE_COVERAGE_RULES_CAPTURE=' $(code_coverage_v_lcov_cap)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(call code_coverage_sanitize,$(PACKAGE_NAME)-$(PACKAGE_VERSION))" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_OPTIONS) $(code_coverage_v_lcov_ign)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_RMOPTS) -@rm -f $(CODE_COVERAGE_OUTPUT_FILE).tmp $(code_coverage_v_genhtml)LANG=C $(GENHTML) $(code_coverage_quiet) $(addprefix --prefix ,$(CODE_COVERAGE_DIRECTORY)) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS) @echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html" '] [CODE_COVERAGE_RULES_CLEAN=' clean: code-coverage-clean distclean: code-coverage-clean code-coverage-clean: -$(LCOV) --directory $(top_builddir) -z -rm -rf $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_FILE).tmp $(CODE_COVERAGE_OUTPUT_DIRECTORY) -find . \( -name "*.gcda" -o -name "*.gcno" -o -name "*.gcov" \) -delete '] ], [ [CODE_COVERAGE_RULES_CHECK=' @echo "Need to reconfigure with --enable-code-coverage" '] CODE_COVERAGE_RULES_CAPTURE="$CODE_COVERAGE_RULES_CHECK" CODE_COVERAGE_RULES_CLEAN='' ]) [CODE_COVERAGE_RULES=' # Code coverage # # Optional: # - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting. # Multiple directories may be specified, separated by whitespace. # (Default: $(top_builddir)) # - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated # by lcov for code coverage. (Default: # $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info) # - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage # reports to be created. (Default: # $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage) # - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage, # set to 0 to disable it and leave empty to stay with the default. # (Default: empty) # - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov # instances. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) # - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov # instances. (Default: $CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) # - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov # - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the # collecting lcov instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) # - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov # instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) # - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering # lcov instance. (Default: empty) # - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov # instance. (Default: $CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) # - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the # genhtml instance. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) # - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml # instance. (Default: $CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) # - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore # # The generated report will be titled using the $(PACKAGE_NAME) and # $(PACKAGE_VERSION). In order to add the current git hash to the title, # use the git-version-gen script, available online. # Optional variables CODE_COVERAGE_DIRECTORY ?= $(top_builddir) CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage CODE_COVERAGE_BRANCH_COVERAGE ?= CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= $(if $(CODE_COVERAGE_BRANCH_COVERAGE),\ --rc lcov_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) CODE_COVERAGE_LCOV_SHOPTS ?= $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool "$(GCOV)" CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= $(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) CODE_COVERAGE_LCOV_OPTIONS ?= $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?= CODE_COVERAGE_LCOV_RMOPTS ?= $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=\ $(if $(CODE_COVERAGE_BRANCH_COVERAGE),\ --rc genhtml_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) CODE_COVERAGE_GENHTML_OPTIONS ?= $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULTS) CODE_COVERAGE_IGNORE_PATTERN ?= code_coverage_v_lcov_cap = $(code_coverage_v_lcov_cap_$(V)) code_coverage_v_lcov_cap_ = $(code_coverage_v_lcov_cap_$(AM_DEFAULT_VERBOSITY)) code_coverage_v_lcov_cap_0 = @echo " LCOV --capture"\ $(CODE_COVERAGE_OUTPUT_FILE); code_coverage_v_lcov_ign = $(code_coverage_v_lcov_ign_$(V)) code_coverage_v_lcov_ign_ = $(code_coverage_v_lcov_ign_$(AM_DEFAULT_VERBOSITY)) code_coverage_v_lcov_ign_0 = @echo " LCOV --remove /tmp/*"\ $(CODE_COVERAGE_IGNORE_PATTERN); code_coverage_v_genhtml = $(code_coverage_v_genhtml_$(V)) code_coverage_v_genhtml_ = $(code_coverage_v_genhtml_$(AM_DEFAULT_VERBOSITY)) code_coverage_v_genhtml_0 = @echo " GEN " $(CODE_COVERAGE_OUTPUT_DIRECTORY); code_coverage_quiet = $(code_coverage_quiet_$(V)) code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY)) code_coverage_quiet_0 = --quiet # sanitizes the test-name: replaces with underscores: dashes and dots code_coverage_sanitize = $(subst -,_,$(subst .,_,$(1))) # Use recursive makes in order to ignore errors during check check-code-coverage:'"$CODE_COVERAGE_RULES_CHECK"' # Capture code coverage data code-coverage-capture: code-coverage-capture-hook'"$CODE_COVERAGE_RULES_CAPTURE"' # Hook rule executed before code-coverage-capture, overridable by the user code-coverage-capture-hook: '"$CODE_COVERAGE_RULES_CLEAN"' GITIGNOREFILES ?= GITIGNOREFILES += $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY) A''M_DISTCHECK_CONFIGURE_FLAGS ?= A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-code-coverage .PHONY: check-code-coverage code-coverage-capture code-coverage-capture-hook code-coverage-clean '] AC_SUBST([CODE_COVERAGE_RULES]) m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([CODE_COVERAGE_RULES])]) ]) libvmod-redis-21.0/m4/ax_pthread.m4000066400000000000000000000505201476735432100171130ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_pthread.html # =========================================================================== # # SYNOPSIS # # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro figures out how to build C programs using POSIX threads. It # sets the PTHREAD_LIBS output variable to the threads library and linker # flags, and the PTHREAD_CFLAGS output variable to any special C compiler # flags that are needed. (The user can also force certain compiler # flags/libs to be tested by setting these environment variables.) # # Also sets PTHREAD_CC to any special C compiler that is needed for # multi-threaded programs (defaults to the value of CC otherwise). (This # is necessary on AIX to use the special cc_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, # but also to link with them as well. For example, you might link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # # If you are only building threaded programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # CC="$PTHREAD_CC" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant # has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to # that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the # PTHREAD_PRIO_INHERIT symbol is defined when compiling with # PTHREAD_CFLAGS. # # ACTION-IF-FOUND is a list of shell commands to run if a threads library # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it # is not found. If ACTION-IF-FOUND is not specified, the default action # will define HAVE_PTHREAD. # # Please let the authors know if this macro fails on any platform, or if # you have any other suggestions or comments. This macro was based on work # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by # Alejandro Forero Cuervo to the autoconf macro repository. We are also # grateful for the helpful feedback of numerous users. # # Updated for Autoconf 2.68 by Daniel Richard G. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2011 Daniel Richard G. # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 23 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_PROG_SED]) AC_LANG_PUSH([C]) ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on Tru64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then ax_pthread_save_CC="$CC" ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) AC_MSG_RESULT([$ax_pthread_ok]) if test "x$ax_pthread_ok" = "xno"; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi CC="$ax_pthread_save_CC" CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 # (Note: HP C rejects this with "bad form for `-t' option") # -pthreads: Solaris/gcc (Note: HP C also rejects) # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads and # -D_REENTRANT too), HP C (must be checked before -lpthread, which # is present but should not be used directly; and before -mthreads, # because the compiler interprets this as "-mt" + "-hreads") # -mthreads: Mingw32/gcc, Lynx/gcc # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case $host_os in freebsd*) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) ax_pthread_flags="-kthread lthread $ax_pthread_flags" ;; hpux*) # From the cc(1) man page: "[-mt] Sets various -D flags to enable # multi-threading and also sets -lpthread." ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" ;; openedition*) # IBM z/OS requires a feature-test macro to be defined in order to # enable POSIX threads at all, so give the user a hint if this is # not set. (We don't define these ourselves, as they can affect # other portions of the system API in unpredictable ways.) AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], [ # if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) AX_PTHREAD_ZOS_MISSING # endif ], [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) ;; solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (N.B.: The stubs are missing # pthread_cleanup_push, or rather a function called by this macro, # so we could check for that, but who knows whether they'll stub # that too in a future libc.) So we'll check first for the # standard Solaris way of linking pthreads (-mt -lpthread). ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" ;; esac # GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) AS_IF([test "x$GCC" = "xyes"], [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) # The presence of a feature test macro requesting re-entrant function # definitions is, on some systems, a strong hint that pthreads support is # correctly enabled case $host_os in darwin* | hpux* | linux* | osf* | solaris*) ax_pthread_check_macro="_REENTRANT" ;; aix*) ax_pthread_check_macro="_THREAD_SAFE" ;; *) ax_pthread_check_macro="--" ;; esac AS_IF([test "x$ax_pthread_check_macro" = "x--"], [ax_pthread_check_cond=0], [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) # Are we compiling with Clang? AC_CACHE_CHECK([whether $CC is Clang], [ax_cv_PTHREAD_CLANG], [ax_cv_PTHREAD_CLANG=no # Note that Autoconf sets GCC=yes for Clang as well as GCC if test "x$GCC" = "xyes"; then AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ # if defined(__clang__) && defined(__llvm__) AX_PTHREAD_CC_IS_CLANG # endif ], [ax_cv_PTHREAD_CLANG=yes]) fi ]) ax_pthread_clang="$ax_cv_PTHREAD_CLANG" ax_pthread_clang_warning=no # Clang needs special handling, because older versions handle the -pthread # option in a rather... idiosyncratic way if test "x$ax_pthread_clang" = "xyes"; then # Clang takes -pthread; it has never supported any other flag # (Note 1: This will need to be revisited if a system that Clang # supports has POSIX threads in a separate library. This tends not # to be the way of modern systems, but it's conceivable.) # (Note 2: On some systems, notably Darwin, -pthread is not needed # to get POSIX threads support; the API is always present and # active. We could reasonably leave PTHREAD_CFLAGS empty. But # -pthread does define _REENTRANT, and while the Darwin headers # ignore this macro, third-party headers might not.) PTHREAD_CFLAGS="-pthread" PTHREAD_LIBS= ax_pthread_ok=yes # However, older versions of Clang make a point of warning the user # that, in an invocation where only linking and no compilation is # taking place, the -pthread option has no effect ("argument unused # during compilation"). They expect -pthread to be passed in only # when source code is being compiled. # # Problem is, this is at odds with the way Automake and most other # C build frameworks function, which is that the same flags used in # compilation (CFLAGS) are also used in linking. Many systems # supported by AX_PTHREAD require exactly this for POSIX threads # support, and in fact it is often not straightforward to specify a # flag that is used only in the compilation phase and not in # linking. Such a scenario is extremely rare in practice. # # Even though use of the -pthread flag in linking would only print # a warning, this can be a nuisance for well-run software projects # that build with -Werror. So if the active version of Clang has # this misfeature, we search for an option to squash it. AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown # Create an alternate version of $ac_link that compiles and # links in two steps (.c -> .o, .o -> exe) instead of one # (.c -> exe), because the warning occurs only in the second # step ax_pthread_save_ac_link="$ac_link" ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" ax_pthread_save_CFLAGS="$CFLAGS" for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" ac_link="$ax_pthread_save_ac_link" AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], [ac_link="$ax_pthread_2step_ac_link" AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], [break]) ]) done ac_link="$ax_pthread_save_ac_link" CFLAGS="$ax_pthread_save_CFLAGS" AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" ]) case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in no | unknown) ;; *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; esac fi # $ax_pthread_clang = yes if test "x$ax_pthread_ok" = "xno"; then for ax_pthread_try_flag in $ax_pthread_flags; do case $ax_pthread_try_flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -mt,pthread) AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) PTHREAD_CFLAGS="-mt" PTHREAD_LIBS="-lpthread" ;; -*) AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) PTHREAD_CFLAGS="$ax_pthread_try_flag" ;; pthread-config) AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) PTHREAD_LIBS="-l$ax_pthread_try_flag" ;; esac ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_LINK_IFELSE([AC_LANG_PROGRAM([#include # if $ax_pthread_check_cond # error "$ax_pthread_check_macro must be defined" # endif static void routine(void *a) { a = 0; } static void *start_routine(void *a) { return a; }], [pthread_t th; pthread_attr_t attr; pthread_create(&th, 0, start_routine, 0); pthread_join(th, 0); pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_cleanup_pop(0) /* ; */])], [ax_pthread_ok=yes], []) CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" AC_MSG_RESULT([$ax_pthread_ok]) AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$ax_pthread_ok" = "xyes"; then ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_CACHE_CHECK([for joinable pthread attribute], [ax_cv_PTHREAD_JOINABLE_ATTR], [ax_cv_PTHREAD_JOINABLE_ATTR=unknown for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], [int attr = $ax_pthread_attr; return attr /* ; */])], [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], []) done ]) AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ test "x$ax_pthread_joinable_attr_defined" != "xyes"], [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$ax_cv_PTHREAD_JOINABLE_ATTR], [Define to necessary symbol if this constant uses a non-standard name on your system.]) ax_pthread_joinable_attr_defined=yes ]) AC_CACHE_CHECK([whether more special flags are required for pthreads], [ax_cv_PTHREAD_SPECIAL_FLAGS], [ax_cv_PTHREAD_SPECIAL_FLAGS=no case $host_os in solaris*) ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" ;; esac ]) AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ test "x$ax_pthread_special_flags_added" != "xyes"], [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" ax_pthread_special_flags_added=yes]) AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], [ax_cv_PTHREAD_PRIO_INHERIT], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int i = PTHREAD_PRIO_INHERIT;]])], [ax_cv_PTHREAD_PRIO_INHERIT=yes], [ax_cv_PTHREAD_PRIO_INHERIT=no]) ]) AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ test "x$ax_pthread_prio_inherit_defined" != "xyes"], [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) ax_pthread_prio_inherit_defined=yes ]) CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" # More AIX lossage: compile with *_r variant if test "x$GCC" != "xyes"; then case $host_os in aix*) AS_CASE(["x/$CC"], [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], [#handle absolute path differently from PATH based program lookup AS_CASE(["x$CC"], [x/*], [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) ;; esac fi fi test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" AC_SUBST([PTHREAD_LIBS]) AC_SUBST([PTHREAD_CFLAGS]) AC_SUBST([PTHREAD_CC]) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test "x$ax_pthread_ok" = "xyes"; then ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) : else ax_pthread_ok=no $2 fi AC_LANG_POP ])dnl AX_PTHREAD libvmod-redis-21.0/redhat/000077500000000000000000000000001476735432100154575ustar00rootroot00000000000000libvmod-redis-21.0/redhat/vmod-redis.spec000066400000000000000000000221351476735432100204070ustar00rootroot00000000000000Summary: Redis VMOD for Varnish Name: vmod-redis Version: 21.0 Release: 1%{?dist} License: BSD URL: https://github.com/carlosabalde/libvmod-redis Group: System Environment/Daemons Source0: libvmod-redis.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Requires: varnish >= 7.7.0, hiredis >= 0.11.0, libev >= 4.03 BuildRequires: make, python-docutils, varnish >= 7.7.0, varnish-devel >= 7.7.0, hiredis-devel >= 0.11.0, libev-devel >= 4.03 %description Redis VMOD for Varnish %prep %setup -n libvmod-redis %build ./autogen.sh ./configure --prefix=/usr/ --docdir='${datarootdir}/doc/%{name}' --libdir='%{_libdir}' %{__make} %{__make} check %install [ %{buildroot} != "/" ] && %{__rm} -rf %{buildroot} %{__make} install DESTDIR=%{buildroot} %clean [ %{buildroot} != "/" ] && %{__rm} -rf %{buildroot} %files %defattr(-,root,root,-) %{_libdir}/varnish*/vmods/lib* %doc /usr/share/doc/%{name}/* %{_mandir}/man?/* %changelog * Tue Mar 18 2025 Carlos Abalde - 21.0-1.20250318 - Migrated to Varnish Cache 7.7.x. * Fri Sep 13 2024 Carlos Abalde - 20.0-1.20240913 - Migrated to Varnish Cache 7.6.x. * Tue Mar 19 2024 Carlos Abalde - 19.0-1.20240319 - Migrated to Varnish Cache 7.5.x. * Fri Sep 15 2023 Carlos Abalde - 18.0-1.20230915 - Migrated to Varnish Cache 7.4.x. * Fri Apr 28 2023 Carlos Abalde - 17.1-1.20230428 - Fixed a couple of Redis Cluster & Redis Sentinel IPv6 issues. - Fixed build under FreeBSD. - Added some missing AN() & AZ(). - Introduced '.easy_execute()'. - Fixed potential segmentation fault due to wrong logging in Sentinel thread. * Wed Mar 15 2023 Carlos Abalde - 17.0-1.20230315 - Migrated to Varnish Cache 7.3.x. * Thu Sep 15 2022 Carlos Abalde - 16.0-1.20220915 - Migrated to Varnish Cache 7.2.x. * Thu Jun 02 2022 Carlos Abalde - 15.1-1.20220602 - Fixed missing string terminator in .stats() method. * Tue Mar 15 2022 Carlos Abalde - 15.0-1.20220315 - Migrated to Varnish Cache 7.1.x. * Wed Jan 12 2022 Carlos Abalde - 14.1-1.20220112 - Added support for streaming & Prometheus format to the .stats() method. - Added CHECK_OBJ_NOTNULL() checks in all free_*() functions. * Wed Sep 15 2021 Carlos Abalde - 14.0-1.20210915 - Migrated to Varnish Cache 7.0.x. * Mon Mar 15 2021 Carlos Abalde - 13.0-1.20210315 - Migrated to Varnish Cache 7.0.x. * Tue Sep 15 2020 Carlos Abalde - 12.0-1.20200915 - Migrated to Varnish Cache 6.5.x. * Fri Jul 17 2020 Carlos Abalde - 11.1-1.20200717 - Added support for larger integers. - Added support for Redis ACLs. - Fixed wrong error message when successfully authenticating Sentinel connections. - Fixed 'SENTINEL masters' execution: send AUTH if password is available. - Improved logging. - Added RESP3 support (depends on future hiredis >= 1.0). - Added TLS support (depends on future hiredis >= 1.0). * Fri Mar 20 2020 Carlos Abalde - 11.0-1.20200320 - Migrated to Varnish Cache 6.4.x. * Fri Feb 21 2020 Carlos Abalde - 10.1-1.20200221 - Added support for Redis Sentinel authentication. - Added Linux Alpine fixes. * Mon Sep 30 2019 Carlos Abalde - 10.0-1.20190930 - Migrated to Varnish Cache 6.3.x. * Thu May 23 2019 Carlos Abalde - 9.1-1.20190523 - Stopped depending on redis-trib.rb. - Added REPLICAOF command (i.e. new SLAVEOF name) support. * Mon Mar 18 2019 Carlos Abalde - 9.0-1.20190318 - Migrated to Varnish Cache 6.2.x. * Tue Sep 18 2018 Carlos Abalde - 8.0-1.20180918 - Migrated to Varnish Cache 6.1.x. * Tue Aug 07 2018 Carlos Abalde - 7.2-1.20180807 - Allowed disabling sickness TTL feature. - Stopped WS-copying input arg in .command() & .push(). * Thu May 03 2018 Carlos Abalde - 7.1-1.20180503 - Fixed execution plan when clustering enabled. * Thu Mar 15 2018 Carlos Abalde - 7.0-1.20180315 - Migrated to Varnish Cache 6.0.x. * Fri Sep 15 2017 Carlos Abalde - 6.0-1.20170915 - Migrated to Varnish Cache 5.2.x. * Thu Jun 01 2017 Carlos Abalde - 5.1-1.20170601 - Added proxied methods. * Fri Mar 17 2017 Carlos Abalde - 5.0-1.20170317 - Migrated to Varnish Cache 5.1.x. * Fri Mar 17 2017 Carlos Abalde - 4.0-1.20170317 - Migrated to Varnish Cache 5.0.x. * Wed Oct 26 2016 Carlos Abalde - 3.11-1.20161026 - Added 'ignore_slaves' option to redis.db(). * Thu Aug 04 2016 Carlos Abalde - 3.10-1.20160804 - Fixed Sentinel-related crash. * Wed Aug 03 2016 Carlos Abalde - 3.9-1.20160803 - Added full password support when clustering is enabled. * Thu Jul 14 2016 Carlos Abalde - 3.8-1.20160714 - Fixed crash when destroying ev loops. * Wed Jul 13 2016 Carlos Abalde - 3.7-1.20160713 - Fixed shared ev loop. * Mon Jul 11 2016 Carlos Abalde - 3.6-1.20160711 - Allowed server-less database instantiation. * Thu Jun 09 2016 Carlos Abalde - 3.5-1.20160609 - Avoided deadlocks enforcing lock ordering + simplifying locking model. * Mon May 02 2016 Carlos Abalde - 3.4-1.20160502 - Stop assuming down flag on +switch-master events. * Wed Apr 20 2016 Carlos Abalde - 3.3-1.20160420 - Added Redis Sentinel support. - Added support for auto-discovery of roles. - Replaced plain pthread mutexes by Varnish locks. - Dynamic allocation of execution plans. - Improved logging. - Added redis.subnets() (previosuly redis.init()). - Improvements & fixes. * Tue Apr 12 2016 Carlos Abalde - 3.2-1.20160412 - Improvements & fixes. * Mon Apr 11 2016 Carlos Abalde - 3.1-1.20160411 - Added support for smart command execution. - Added redis.init(), including weights + subnet masks. - Added type (master, slave, cluster) and sickness TTL to redis.db(). - Added master / slave selection to .execute(). - Improvements & fixes. * Mon Apr 04 2016 Carlos Abalde - 3.0-1.20160404 - New version numbering scheme. * Mon Feb 29 2016 Carlos Abalde - 0.3.6-1.20160229 - Improved VSL / syslog logging. * Tue Feb 09 2016 Carlos Abalde - 0.3.5-1.20160209 - Added AUTH support. * Tue Dec 22 2015 Carlos Abalde - 0.3.4-1.20151222 - Added .counter(). - Improved handling of -MOVED errors. - Simplified & improved internals. * Tue Dec 22 2015 Carlos Abalde - 0.3.3-1.20151222 - Improvements & fixes. * Mon Dec 21 2015 Carlos Abalde - 0.3.2-1.20151221 - Added .stats(). * Wed Dec 16 2015 Carlos Abalde - 0.3.1-1.20151216 - Removed support for server tags. - Removed .add_cserver(). - Removed .server(). * Tue Dec 15 2015 Carlos Abalde - 0.3.0-1.20151215 - Added support for multiple clusters. - Added .retries(). - Removed redis.fini(). - Improved manual page. * Mon Jun 08 2015 Carlos Abalde - 0.2.7-1.20150608 - Fixed memory leak during redis.fini(). - Fixed initialization / reset of command execution timeout. - Added Redis Cluster tests. * Tue May 26 2015 Carlos Abalde - 0.2.6-1.20150526 - Fixed bug when processing -MOVED and -ASK errors. - Updated files borrowed from the Redis implementation. * Tue May 12 2015 Carlos Abalde - 0.2.5-1.20150512 - Do not require C99 standard. * Fri Apr 17 2015 Carlos Abalde - 0.2.4-1.20150417 - Added support for timeouts when executing commands. - Maximum number of Redis Cluster hops is now configurable. * Wed Jan 28 2015 Carlos Abalde - 0.2.3-1.20150128 - Added support for hiredis 0.12.1 (redisEnableKeepAlive). - Updated Redis Cluster key -> slot calculation. * Fri Dec 19 2014 Carlos Abalde - 0.2.2-1.20141219 - Added support for command retries. * Wed Dec 17 2014 Carlos Abalde - 0.2.1-1.20141217 - Added redis.replied(). - Minor fixes. * Tue Dec 16 2014 Carlos Abalde - 0.2.0-1.20141216 - Added Redis Cluster support. - Minor improvements & fixes. * Sun Dec 14 2014 Carlos Abalde - 0.1.3-1.20141214 - Added support for shared pools of Redis connections. - Refactor to simplify future support of Redis Cluster. * Thu Oct 23 2014 Carlos Abalde - 0.1.2-1.20141023 - Discard Redis contexts when connections are hung up by the server. * Wed Sep 17 2014 Carlos Abalde - 0.1.1-1.20140917 - Added missing WS_Dup()'s / WS_Copy()'s. * Fri Aug 22 2014 Carlos Abalde - 0.1-1.20140822 - Initial version. libvmod-redis-21.0/src/000077500000000000000000000000001476735432100147775ustar00rootroot00000000000000libvmod-redis-21.0/src/Makefile.am000066400000000000000000000017471476735432100170440ustar00rootroot00000000000000AM_CFLAGS = $(VARNISHAPI_CFLAGS) $(CODE_COVERAGE_CFLAGS) -Wall -DEV_COMPAT3=1 AM_LDFLAGS = $(VARNISHAPI_LIBS) $(VMOD_LDFLAGS) $(CODE_COVERAGE_LDFLAGS) vmod_LTLIBRARIES = libvmod_redis.la libvmod_redis_la_SOURCES = \ crc16.c crc16.h \ sha1.c sha1.h \ cluster.c cluster.h \ core.c core.h \ sentinel.c sentinel.h \ vmod_redis.c nodist_libvmod_redis_la_SOURCES = \ vcc_redis_if.c \ vcc_redis_if.h dist_man_MANS = vmod_redis.3 @BUILD_VMOD_REDIS@ AM_TESTS_ENVIRONMENT = \ PATH="$(VMOD_TEST_PATH)" \ LD_LIBRARY_PATH="$(VARNISH_LIBRARY_PATH)" TEST_EXTENSIONS = .vtc VTC_LOG_COMPILER = $(abs_srcdir)/tests/runner.sh varnishtest AM_VTC_LOG_FLAGS = -v -Dvmod_redis="$(VMOD_REDIS)" TESTS = @VMOD_TESTS@ EXTRA_DIST = \ tests/assets/hashslot-keys.txt \ tests/assets/tls-ca-certificate.crt \ tests/assets/tls-ca-certificate.key \ tests/assets/tls-certificate.crt \ tests/assets/tls-certificate.key \ tests/runner.sh \ vmod_redis.vcc \ $(VMOD_TESTS) DISTCLEANFILES = vmod_vcs_version.txt libvmod-redis-21.0/src/cluster.c000066400000000000000000000401201476735432100166210ustar00rootroot00000000000000#include "config.h" #include #include #include #include #include #include #include #include "cache/cache.h" #include "crc16.h" #include "core.h" #include "cluster.h" #define BANNED_COMMANDS "|INFO|MULTI|EXEC|SLAVEOF|REPLICAOF|CONFIG|SHUTDOWN|SCRIPT|" #define KEY_INDEX3_COMMANDS "|EVAL|EVALSHA|" #define CLUSTER_DISCOVERY_COMMAND "CLUSTER SLOTS" static void unsafe_discover_slots( VRT_CTX, struct vmod_redis_db *db, vcl_state_t *config, redis_server_t *server); static int get_key_index(const char *command); static unsigned get_cluster_slot(const char *key); void discover_cluster_slots( VRT_CTX, struct vmod_redis_db *db, vcl_state_t *config, redis_server_t *server) { Lck_Lock(&config->mutex); Lck_Lock(&db->mutex); unsafe_discover_slots(ctx, db, config, server); Lck_Unlock(&db->mutex); Lck_Unlock(&config->mutex); } redisReply * cluster_execute( VRT_CTX, struct vmod_redis_db *db, vcl_state_t *config, task_state_t *state, struct timeval timeout, unsigned max_retries, unsigned argc, const char *argv[], unsigned *retries, unsigned master) { // Initializations. redisReply *result = NULL; // Can the command be executed in a clustered setup? int index = get_key_index(argv[0]); if ((index > 0) && (index < argc)) { // Initializations. unsigned slot = get_cluster_slot(argv[index]); unsigned hops = db->cluster.max_hops > 0 ? db->cluster.max_hops : UINT_MAX; unsigned asking = 0; unsigned hop = 0; redis_server_t *server = NULL; // Execute command, retrying and following redirections up to // some limit. while (result == NULL) { // Execute command: // - server != NULL ==> only include 'server' in the execution plan. // - !master ==> use READONLY + READWRITE when dealing with slaves. // - unknown slot ==> random server selection. result = redis_execute( ctx, db, state, timeout, max_retries, argc, argv, retries, server, asking, master, slot); // Reset flags. asking = 0; hop = 0; server = NULL; // Check reply. if (result != NULL) { // Is this a MOVED or ASK error reply? if ((result->type == REDIS_REPLY_ERROR) && ((strncmp(result->str, "MOVED", 5) == 0) || (strncmp(result->str, "ASK", 3) == 0))) { // Extract location (e.g. ASK 3999 127.0.0.1:6381). char *ptr = strchr(result->str, ' '); AN(ptr); char *location = strchr(ptr + 1, ' '); AN(location); location++; // Set hop flag. hop = 1; // Get config & database locks. Lck_Lock(&config->mutex); Lck_Lock(&db->mutex); // Add / fetch server. server = unsafe_add_redis_server( ctx, db, config, location, REDIS_SERVER_TBD_ROLE); AN(server); // ASK vs. MOVED. if (strncmp(result->str, "MOVED", 3) == 0) { // Update stats. db->stats.cluster.replies.moved++; // Rediscover the cluster topology asking to the server // in the MOVED reply (or to any other server if that // one fails). Giving priority to the server in the // MOVED reply ensures that the right topology will be // discovered even when it has not yet been propagated // to the whole cluster. // // Even though using 'server' in the next execution plan // is not strictly required because the cluster topology // has just been rediscovered, this allows handling in a // nice way rw commands sent to ro slaves. // // XXX: at the moment this implementation may result in // multiple threads executing multiple -serialized- // cluster discoveries. unsafe_discover_slots(ctx, db, config, server); } else { // Update stats. db->stats.cluster.replies.ask++; // Next attempt should send a ASKING command to the // server in the ASK reply. asking = 1; } // Release config & database locks. Lck_Unlock(&db->mutex); Lck_Unlock(&config->mutex); // Release reply object. freeReplyObject(result); result = NULL; // Execution completed: some reply, excluding cluster // redirections. } else { break; } } // Try again? if (result == NULL) { if (hop && (hops > 0) && (*retries <= max_retries)) { hops--; } else { break; } } } // Too many redirections? if (hops == 0) { REDIS_LOG_ERROR(ctx, "Too many redirections while executing cluster command (command=%s, db=%s)", argv[0], db->name); } // Invalid Redis Cluster command. } else { REDIS_LOG_ERROR(ctx, "Invalid cluster command (command=%s, db=%s)", argv[0], db->name); } // Done! return result; } /****************************************************************************** * UTILITIES. *****************************************************************************/ static void unsafe_add_slot( VRT_CTX, struct vmod_redis_db *db, vcl_state_t *config, unsigned start, unsigned stop, char *host, int port, enum REDIS_SERVER_ROLE role) { // Assertions. Lck_AssertHeld(&config->mutex); Lck_AssertHeld(&db->mutex); // Add / update server. char location[256]; snprintf(location, sizeof(location), "%s:%d", host, port); redis_server_t *server = unsafe_add_redis_server(ctx, db, config, location, role); AN(server); // Register slots. for (int i = start; i <= stop; i++) { server->cluster.slots[i] = 1; } } static unsigned unsafe_discover_slots_aux( VRT_CTX, struct vmod_redis_db *db, vcl_state_t *config, redis_server_t *server) { // Assertions. Lck_AssertHeld(&config->mutex); Lck_AssertHeld(&db->mutex); assert(server->location.type == REDIS_SERVER_LOCATION_HOST_TYPE); // Log event. REDIS_LOG_INFO(ctx, "Discovery of cluster topology started (db=%s, server=%s)", db->name, server->location.raw); // Initializations. unsigned done = 0; // Create context. redisContext *rcontext; if ((db->connection_timeout.tv_sec > 0) || (db->connection_timeout.tv_usec > 0)) { rcontext = redisConnectWithTimeout( server->location.parsed.address.host, server->location.parsed.address.port, db->connection_timeout); } else { rcontext = redisConnect( server->location.parsed.address.host, server->location.parsed.address.port); } // Check context. if ((rcontext != NULL) && (!rcontext->err)) { // Optionally setup TLS & submit AUTH / HELLO command. REDIS_BLESS_CONTEXT( ctx, rcontext, server->db, "Failed to initialize cluster discovery connection", "db=%s, server=%s", server->db->name, server->location.raw); // Do not continue if failed to initialize the connection. if (rcontext != NULL) { // Set command execution timeout. int tr = redisSetTimeout(rcontext, db->command_timeout); if (tr != REDIS_OK) { REDIS_LOG_ERROR(ctx, "Failed to set cluster discovery command execution timeout (error=%d, db=%s, server=%s)", tr, server->db->name, server->location.raw); } // Send command. redisReply *reply = redisCommand(rcontext, CLUSTER_DISCOVERY_COMMAND); // Check reply. if ((!rcontext->err) && (reply != NULL) && (reply->type == REDIS_REPLY_ARRAY)) { // Reset previous slots. redis_server_t *iserver; for (unsigned iweight = 0; iweight < NREDIS_SERVER_WEIGHTS; iweight++) { for (enum REDIS_SERVER_ROLE irole = 0; irole < NREDIS_SERVER_ROLES; irole++) { VTAILQ_FOREACH(iserver, &db->servers[iweight][irole], list) { for (int i = 0; i < NREDIS_CLUSTER_SLOTS; i++) { iserver->cluster.slots[i] = 0; } } } } // Extract slots. for (int i = 0; i < reply->elements; i++) { if ((reply->element[i]->type == REDIS_REPLY_ARRAY) && (reply->element[i]->elements >= 3) && (reply->element[i]->element[0]->type == REDIS_REPLY_INTEGER) && (reply->element[i]->element[1]->type == REDIS_REPLY_INTEGER) && (reply->element[i]->element[2]->type == REDIS_REPLY_ARRAY) && (reply->element[i]->element[2]->elements >= 2) && (reply->element[i]->element[2]->element[0]->type == REDIS_REPLY_STRING) && (reply->element[i]->element[2]->element[1]->type == REDIS_REPLY_INTEGER)) { // Extract slot data. int start = reply->element[i]->element[0]->integer; int end = reply->element[i]->element[1]->integer; // Check slot data. if ((start >= 0) && (start < NREDIS_CLUSTER_SLOTS) && (end >= 0) && (end < NREDIS_CLUSTER_SLOTS)) { unsafe_add_slot( ctx, db, config, start, end, reply->element[i]->element[2]->element[0]->str, reply->element[i]->element[2]->element[1]->integer, REDIS_SERVER_MASTER_ROLE); // Extract slave servers data. for (int j = 3; j < reply->element[i]->elements; j++) { if ((reply->element[i]->element[j]->type == REDIS_REPLY_ARRAY) && (reply->element[i]->element[j]->elements >= 2) && (reply->element[i]->element[j]->element[0]->type == REDIS_REPLY_STRING) && (reply->element[i]->element[j]->element[1]->type == REDIS_REPLY_INTEGER)) { unsafe_add_slot( ctx, db, config, start, end, reply->element[i]->element[j]->element[0]->str, reply->element[i]->element[j]->element[1]->integer, REDIS_SERVER_SLAVE_ROLE); } } } } } // Stop execution. done = 1; db->stats.cluster.discoveries.total++; } else { REDIS_LOG_ERROR(ctx, "Failed to execute cluster discovery command (error=%d, db=%s, server=%s): %s", rcontext->err, db->name, server->location.raw, HIREDIS_ERRSTR(rcontext, reply)); db->stats.cluster.discoveries.failed++; } // Release reply. if (reply != NULL) { freeReplyObject(reply); } } else { db->stats.cluster.discoveries.failed++; } } else { if (rcontext != NULL) { REDIS_LOG_ERROR(ctx, "Failed to establish cluster discovery connection (error=%d, db=%s, server=%s): %s", rcontext->err, db->name, server->location.raw, HIREDIS_ERRSTR(rcontext)); } else { REDIS_LOG_ERROR(ctx, "Failed to establish cluster discovery connection (db=%s, server=%s)", db->name, server->location.raw); } db->stats.cluster.discoveries.failed++; } // Release context. if (rcontext != NULL) { redisFree(rcontext); } // Done. return done; } static void unsafe_discover_slots( VRT_CTX, struct vmod_redis_db *db, vcl_state_t *config, redis_server_t *server) { // Assertions. Lck_AssertHeld(&config->mutex); Lck_AssertHeld(&db->mutex); // Contact already known servers and try to fetch the slots-servers mapping. // Always use the provided server instance in the first place. if (!unsafe_discover_slots_aux(ctx, db, config, server)) { for (unsigned iweight = 0; iweight < NREDIS_SERVER_WEIGHTS; iweight++) { for (enum REDIS_SERVER_ROLE irole = 0; irole < NREDIS_SERVER_ROLES; irole++) { redis_server_t *iserver; VTAILQ_FOREACH(iserver, &db->servers[iweight][irole], list) { CHECK_OBJ_NOTNULL(iserver, REDIS_SERVER_MAGIC); if ((iserver != server) && (unsafe_discover_slots_aux(ctx, db, config, iserver))) { // Lists of servers are only modified on a successful // discovery ==> it's safe to iterate on these data // structures because once they are modified the // iteration will finish. return; } } } } } } static int get_key_index(const char *command) { // Initializations. char buffer[64]; snprintf(buffer, sizeof(buffer), "|%s|", command); // Some commands (e.g. INFO) are explicitly banned returning -1. Some other // commands (e.g. EVAL) are explicitly handled to return the correct // location of the key value. Finally, all other commands are assumed to // contain the key as the first argument after the command name. This is // indeed the case for most commands, and when it is not true the cluster // redirection will point to the right node anyway. // // XXX: beware that cluster redirections trigger expensive cluster // rediscoveries ==> they must be avoided at all costs. if (strcasestr(BANNED_COMMANDS, buffer) != NULL) { return -1; } else if (strcasestr(KEY_INDEX3_COMMANDS, buffer) != NULL) { return 3; } return 1; } static unsigned get_cluster_slot(const char *key) { // Start-end indexes of '{'' and '}'. int s, e; // Search the first occurrence of '{'. int keylen = strlen(key); for (s = 0; s < keylen; s++) { if (key[s] == '{') { break; } } // No '{'? Hash the whole key. This is the base case. if (s == keylen) { return crc16(key, keylen) & (NREDIS_CLUSTER_SLOTS - 1); } // '{' found? Check if we have the corresponding '}'. for (e = s+1; e < keylen; e++){ if (key[e] == '}') { break; } } // No '}' or nothing between {}? Hash the whole key. if ((e == keylen) || (e == s + 1)) { return crc16(key, keylen) & (NREDIS_CLUSTER_SLOTS - 1); } // If we are here there is both a '{' and a '}' on its right. Hash // what is in the middle between '{' and '}'. return crc16(key + s + 1, e - s - 1) & (NREDIS_CLUSTER_SLOTS - 1); } libvmod-redis-21.0/src/cluster.h000066400000000000000000000007171476735432100166360ustar00rootroot00000000000000#ifndef CLUSTER_H_INCLUDED #define CLUSTER_H_INCLUDED #include #include "core.h" void discover_cluster_slots( VRT_CTX, struct vmod_redis_db *db, vcl_state_t *config, redis_server_t *server); redisReply *cluster_execute( VRT_CTX, struct vmod_redis_db *db, vcl_state_t *config, task_state_t *state, struct timeval timeout, unsigned max_retries, unsigned argc, const char *argv[], unsigned *retries, unsigned master); #endif libvmod-redis-21.0/src/core.c000066400000000000000000001505121476735432100160770ustar00rootroot00000000000000#include "config.h" #include #include #include #include #include #include #include #ifdef TLS_ENABLED #include #endif #include #ifdef __FreeBSD__ #include #endif #include "cache/cache.h" #include "sha1.h" #include "sentinel.h" #include "core.h" #define ROLE_DISCOVERY_COMMAND "ROLE" vmod_state_t vmod_state = { .mutex = PTHREAD_MUTEX_INITIALIZER, .version = 0, .locks.refs = 0, .locks.vsc_seg = NULL, .locks.config = NULL, .locks.db = NULL }; struct plan { // Ordered list of private contexts, including a reference to the next item // to be considered during the execution. This is only used when the // database is configured to use private contexts. struct { unsigned n; redis_context_t **list; unsigned next; } contexts; // Ordered circular list of servers, including a reference to the next item // to be considered during the execution. struct { unsigned n; redis_server_t **list; unsigned next; } servers; }; static enum REDIS_SERVER_ROLE unsafe_discover_redis_server_role( VRT_CTX, redis_server_t *server); static struct plan *plan_execution( VRT_CTX, struct vmod_redis_db *db, task_state_t *state, unsigned size, redis_server_t *server, unsigned master, unsigned slot); static redis_context_t *lock_redis_context( VRT_CTX, struct vmod_redis_db *db, task_state_t *state, struct plan *plan); static void unlock_redis_context( VRT_CTX, struct vmod_redis_db *db, task_state_t *state, redis_context_t *context); static redisReply *get_redis_repy( VRT_CTX, redis_context_t *context, struct timeval timeout, unsigned argc, const char *argv[], unsigned asking); static const char *sha1(VRT_CTX, const char *script); redis_server_t * new_redis_server( struct vmod_redis_db *db, const char *location, enum REDIS_SERVER_ROLE role) { redis_server_t *result; ALLOC_OBJ(result, REDIS_SERVER_MAGIC); AN(result); char *ptr = strrchr(location, ':'); if (ptr != NULL) { result->location.type = REDIS_SERVER_LOCATION_HOST_TYPE; result->location.parsed.address.host = strndup(location, ptr - location); AN(result->location.parsed.address.host); result->location.parsed.address.port = atoi(ptr + 1); } else { result->location.type = REDIS_SERVER_LOCATION_SOCKET_TYPE; result->location.parsed.path = strdup(location); AN(result->location.parsed.path); } // Do not continue if this is a clustered database but the location is not // provided using the IP + port format. struct in_addr ia4; struct in6_addr ia6; if ((db->cluster.enabled) && ((result->location.type != REDIS_SERVER_LOCATION_HOST_TYPE) || ((inet_pton(AF_INET, result->location.parsed.address.host, &ia4) == 0) && (inet_pton(AF_INET6, result->location.parsed.address.host, &ia6) == 0)))) { free((void *) result->location.parsed.address.host); FREE_OBJ(result); return NULL; } result->db = db; result->location.raw = strdup(location); AN(result->location.raw); result->role = role; result->weight = 0; AZ(pthread_cond_init(&result->pool.cond, NULL)); result->pool.ncontexts = 0; VTAILQ_INIT(&result->pool.free_contexts); VTAILQ_INIT(&result->pool.busy_contexts); for (int i = 0; i < NREDIS_CLUSTER_SLOTS; i++) { result->cluster.slots[i] = 0; } result->sickness.tst = 0; result->sickness.exp = 0; // Done! return result; } void free_redis_server(redis_server_t *server) { CHECK_OBJ_NOTNULL(server, REDIS_SERVER_MAGIC); server->db = NULL; free((void *) server->location.raw); server->location.raw = NULL; switch (server->location.type) { case REDIS_SERVER_LOCATION_HOST_TYPE: free((void *) server->location.parsed.address.host); server->location.parsed.address.host = NULL; server->location.parsed.address.port = 0; break; case REDIS_SERVER_LOCATION_SOCKET_TYPE: free((void *) server->location.parsed.path); server->location.parsed.path = NULL; break; } server->role = REDIS_SERVER_TBD_ROLE; server->weight = 0; AZ(pthread_cond_destroy(&server->pool.cond)); server->pool.ncontexts = 0; redis_context_t *icontext; while (!VTAILQ_EMPTY(&server->pool.free_contexts)) { icontext = VTAILQ_FIRST(&server->pool.free_contexts); CHECK_OBJ_NOTNULL(icontext, REDIS_CONTEXT_MAGIC); VTAILQ_REMOVE(&server->pool.free_contexts, icontext, list); free_redis_context(icontext); } while (!VTAILQ_EMPTY(&server->pool.busy_contexts)) { icontext = VTAILQ_FIRST(&server->pool.busy_contexts); CHECK_OBJ_NOTNULL(icontext, REDIS_CONTEXT_MAGIC); VTAILQ_REMOVE(&server->pool.busy_contexts, icontext, list); free_redis_context(icontext); } for (int i = 0; i < NREDIS_CLUSTER_SLOTS; i++) { server->cluster.slots[i] = 0; } server->sickness.tst = 0; server->sickness.exp = 0; FREE_OBJ(server); } redis_context_t * new_redis_context( redis_server_t *server, redisContext *rcontext, time_t tst) { redis_context_t *result; ALLOC_OBJ(result, REDIS_CONTEXT_MAGIC); AN(result); result->server = server; result->rcontext = rcontext; result->version = vmod_state.version; result->tst = tst; return result; } void free_redis_context(redis_context_t *context) { CHECK_OBJ_NOTNULL(context, REDIS_CONTEXT_MAGIC); context->server = NULL; if (context->rcontext != NULL) { redisFree(context->rcontext); context->rcontext = NULL; } context->version = 0; context->tst = 0; FREE_OBJ(context); } struct vmod_redis_db * new_vmod_redis_db( vcl_state_t *config, const char *name, struct timeval connection_timeout, unsigned connection_ttl, struct timeval command_timeout, unsigned max_command_retries, unsigned shared_connections, unsigned max_connections, enum REDIS_PROTOCOL protocol, #ifdef TLS_ENABLED redisSSLContext *tls_ssl_ctx, #endif const char *user, const char *password, unsigned sickness_ttl, unsigned ignore_slaves, unsigned clustered, unsigned max_cluster_hops) { struct vmod_redis_db *result; ALLOC_OBJ(result, VMOD_REDIS_DATABASE_MAGIC); AN(result); Lck_New(&result->mutex, vmod_state.locks.db); result->config = config; for (unsigned weight = 0; weight < NREDIS_SERVER_WEIGHTS; weight++) { for (enum REDIS_SERVER_ROLE role = 0; role < NREDIS_SERVER_ROLES; role++) { VTAILQ_INIT(&result->servers[weight][role]); } } result->name = strdup(name); AN(result->name); result->connection_timeout = connection_timeout; result->connection_ttl = connection_ttl; result->command_timeout = command_timeout; result->max_command_retries = max_command_retries; result->shared_connections = shared_connections; result->max_connections = max_connections; result->protocol = protocol; #ifdef TLS_ENABLED result->tls_ssl_ctx = tls_ssl_ctx; #endif if (strlen(user) > 0) { result->user = strdup(user); AN(result->user); } else { result->user = NULL; } if (strlen(password) > 0) { result->password = strdup(password); AN(result->password); } else { result->password = NULL; } result->sickness_ttl = sickness_ttl; result->ignore_slaves = ignore_slaves; result->cluster.enabled = clustered; result->cluster.max_hops = max_cluster_hops; result->stats.servers.total = 0; result->stats.servers.failed = 0; result->stats.connections.total = 0; result->stats.connections.failed = 0; result->stats.connections.dropped.error = 0; result->stats.connections.dropped.hung_up = 0; result->stats.connections.dropped.overflow = 0; result->stats.connections.dropped.ttl = 0; result->stats.connections.dropped.version = 0; result->stats.connections.dropped.sick = 0; result->stats.workers.blocked = 0; result->stats.commands.total = 0; result->stats.commands.failed = 0; result->stats.commands.retried = 0; result->stats.commands.error = 0; result->stats.commands.noscript = 0; result->stats.cluster.discoveries.total = 0; result->stats.cluster.discoveries.failed = 0; result->stats.cluster.replies.moved = 0; result->stats.cluster.replies.ask = 0; return result; } void free_vmod_redis_db(struct vmod_redis_db *db) { CHECK_OBJ_NOTNULL(db, VMOD_REDIS_DATABASE_MAGIC); Lck_Delete(&db->mutex); db->config = NULL; for (unsigned weight = 0; weight < NREDIS_SERVER_WEIGHTS; weight++) { for (enum REDIS_SERVER_ROLE role = 0; role < NREDIS_SERVER_ROLES; role++) { redis_server_t *iserver; while (!VTAILQ_EMPTY(&db->servers[weight][role])) { iserver = VTAILQ_FIRST(&db->servers[weight][role]); CHECK_OBJ_NOTNULL(iserver, REDIS_SERVER_MAGIC); VTAILQ_REMOVE(&db->servers[weight][role], iserver, list); free_redis_server(iserver); } } } free((void *) db->name); db->name = NULL; db->connection_timeout = (struct timeval){ 0 }; db->connection_ttl = 0; db->command_timeout = (struct timeval){ 0 }; db->max_command_retries = 0; db->shared_connections = 0; db->max_connections = 0; db->protocol = REDIS_PROTOCOL_DEFAULT; #ifdef TLS_ENABLED if (db->tls_ssl_ctx != NULL) { redisFreeSSLContext(db->tls_ssl_ctx); db->tls_ssl_ctx = NULL; } #endif if (db->user != NULL) { free((void *) db->user); db->user = NULL; } if (db->password != NULL) { free((void *) db->password); db->password = NULL; } db->sickness_ttl = 0; db->ignore_slaves = 0; db->cluster.enabled = 0; db->cluster.max_hops = 0; db->stats.servers.total = 0; db->stats.servers.failed = 0; db->stats.connections.total = 0; db->stats.connections.failed = 0; db->stats.connections.dropped.error = 0; db->stats.connections.dropped.hung_up = 0; db->stats.connections.dropped.overflow = 0; db->stats.connections.dropped.ttl = 0; db->stats.connections.dropped.version = 0; db->stats.connections.dropped.sick = 0; db->stats.workers.blocked = 0; db->stats.commands.total = 0; db->stats.commands.failed = 0; db->stats.commands.retried = 0; db->stats.commands.error = 0; db->stats.commands.noscript = 0; db->stats.cluster.discoveries.total = 0; db->stats.cluster.discoveries.failed = 0; db->stats.cluster.replies.moved = 0; db->stats.cluster.replies.ask = 0; FREE_OBJ(db); } task_state_t * new_task_state() { task_state_t *result; ALLOC_OBJ(result, TASK_STATE_MAGIC); AN(result); result->ncontexts = 0; VTAILQ_INIT(&result->contexts); result->db = NULL; result->command.db = NULL; result->command.timeout = (struct timeval){ 0 }; result->command.max_retries = 0; result->command.argc = 0; result->command.reply = NULL; return result; } void free_task_state(task_state_t *state) { CHECK_OBJ_NOTNULL(state, TASK_STATE_MAGIC); state->ncontexts = 0; redis_context_t *icontext; while (!VTAILQ_EMPTY(&state->contexts)) { icontext = VTAILQ_FIRST(&state->contexts); CHECK_OBJ_NOTNULL(icontext, REDIS_CONTEXT_MAGIC); VTAILQ_REMOVE(&state->contexts, icontext, list); free_redis_context(icontext); } state->db = NULL; state->command.db = NULL; state->command.timeout = (struct timeval){ 0 }; state->command.max_retries = 0; state->command.argc = 0; if (state->command.reply != NULL) { freeReplyObject(state->command.reply); } FREE_OBJ(state); } vcl_state_t * new_vcl_state() { vcl_state_t *result; ALLOC_OBJ(result, VCL_STATE_MAGIC); AN(result); Lck_New(&result->mutex, vmod_state.locks.config); VTAILQ_INIT(&result->subnets); VTAILQ_INIT(&result->dbs); result->sentinels.locations = NULL; result->sentinels.period = 0; result->sentinels.connection_timeout = (struct timeval){ 0 }; result->sentinels.command_timeout = (struct timeval){ 0 }; result->sentinels.protocol = REDIS_PROTOCOL_DEFAULT; #ifdef TLS_ENABLED result->sentinels.tls = 0; result->sentinels.tls_cafile = NULL; result->sentinels.tls_capath = NULL; result->sentinels.tls_certfile = NULL; result->sentinels.tls_keyfile = NULL; result->sentinels.tls_sni = NULL; #endif result->sentinels.password = NULL; result->sentinels.thread = 0; result->sentinels.active = 0; result->sentinels.discovery = 0; return result; } void free_vcl_state(vcl_state_t *priv) { // XXX: associated lock class (i.e. vmod_state.locks.config) has already // been destroyed during handle_vcl_discard_event(). It's too late to call // Lck_Delete(). // Lck_Delete(&priv->mutex); CHECK_OBJ_NOTNULL(priv, VCL_STATE_MAGIC); subnet_t *isubnet; while (!VTAILQ_EMPTY(&priv->subnets)) { isubnet = VTAILQ_FIRST(&priv->subnets); CHECK_OBJ_NOTNULL(isubnet, SUBNET_MAGIC); VTAILQ_REMOVE(&priv->subnets, isubnet, list); free_subnet(isubnet); } database_t *idb; while (!VTAILQ_EMPTY(&priv->dbs)) { idb = VTAILQ_FIRST(&priv->dbs); CHECK_OBJ_NOTNULL(idb, DATABASE_MAGIC); VTAILQ_REMOVE(&priv->dbs, idb, list); free_database(idb); } if (priv->sentinels.locations != NULL) { free((void *) priv->sentinels.locations); priv->sentinels.locations = NULL; } priv->sentinels.period = 0; priv->sentinels.connection_timeout = (struct timeval){ 0 }; priv->sentinels.command_timeout = (struct timeval){ 0 }; priv->sentinels.protocol = REDIS_PROTOCOL_DEFAULT; #ifdef TLS_ENABLED priv->sentinels.tls = 0; if (priv->sentinels.tls_cafile != NULL) { free((void *) priv->sentinels.tls_cafile); priv->sentinels.tls_cafile = NULL; } if (priv->sentinels.tls_capath != NULL) { free((void *) priv->sentinels.tls_capath); priv->sentinels.tls_capath = NULL; } if (priv->sentinels.tls_certfile != NULL) { free((void *) priv->sentinels.tls_certfile); priv->sentinels.tls_certfile = NULL; } if (priv->sentinels.tls_keyfile != NULL) { free((void *) priv->sentinels.tls_keyfile); priv->sentinels.tls_keyfile = NULL; } if (priv->sentinels.tls_sni != NULL) { free((void *) priv->sentinels.tls_sni); priv->sentinels.tls_sni = NULL; } #endif if (priv->sentinels.password != NULL) { free((void *) priv->sentinels.password); priv->sentinels.password = NULL; } priv->sentinels.thread = 0; priv->sentinels.active = 0; priv->sentinels.discovery = 0; FREE_OBJ(priv); } subnet_t * new_subnet(unsigned weight, struct in_addr ia4, unsigned bits) { subnet_t *result; ALLOC_OBJ(result, SUBNET_MAGIC); AN(result); result->weight = weight; result->mask.s_addr = (bits == 0 ? 0x0 : (0xffffffff << (32 - bits))); result->address.s_addr = ntohl(ia4.s_addr) & result->mask.s_addr; return result; } void free_subnet(subnet_t *subnet) { CHECK_OBJ_NOTNULL(subnet, SUBNET_MAGIC); subnet->weight = 0; subnet->mask = (struct in_addr){ 0 }; subnet->address = (struct in_addr){ 0 }; FREE_OBJ(subnet); } database_t * new_database(struct vmod_redis_db *db) { database_t *result; ALLOC_OBJ(result, DATABASE_MAGIC); AN(result); result->db = db; return result; } void free_database(database_t *db) { CHECK_OBJ_NOTNULL(db, DATABASE_MAGIC); free_vmod_redis_db(db->db); db->db = NULL; FREE_OBJ(db); } redisReply * redis_execute( VRT_CTX, struct vmod_redis_db *db, task_state_t *state, struct timeval timeout, unsigned max_retries, unsigned argc, const char *argv[], unsigned *retries, redis_server_t *server, unsigned asking, unsigned master, unsigned slot) { // Assertions. assert(*retries <= max_retries); // Initializations. redisReply *result = NULL; // Build the execution plan. struct plan *plan = plan_execution( ctx, db, state, (*retries > 0) ? max_retries - *retries : 1 + max_retries - *retries, server, master, slot); // Do not continue if an execution plan is not available of if it's empty. if ((plan != NULL) && ((plan->contexts.n > 0) || (plan->servers.n > 0))) { // Execute command, retrying up to some limit. while (result == NULL) { // Initializations. redis_context_t *context = lock_redis_context(ctx, db, state, plan); // Do not continue if a context is not available. if (context != NULL) { // Initializations. unsigned done = 0; unsigned failed_ws = 0; // When executing EVAL commands, first try with EVALSHA. if ((strcasecmp(argv[0], "EVAL") == 0) && (argc >= 2)) { // Replace EVAL with EVALSHA. argv[0] = WS_Copy(ctx->ws, "EVALSHA", -1); if (argv[0] == NULL) { failed_ws = 1; goto unlock; } const char *script = argv[1]; argv[1] = sha1(ctx, script); if (argv[1] == NULL) { failed_ws = 1; goto unlock; } // Execute the EVALSHA command. result = get_redis_repy(ctx, context, timeout, argc, argv, asking); // Check reply. If replied with a NOSCRIPT, the original // EVAL command should be executed to register the script // for the first time in the Redis server. if (!context->rcontext->err && (result != NULL) && (result->type == REDIS_REPLY_ERROR) && (strncmp(result->str, "NOSCRIPT", 8) == 0)) { // Replace EVALSHA with EVAL. argv[0] = WS_Copy(ctx->ws, "EVAL", -1); if (argv[0] == NULL) { failed_ws = 1; goto unlock; } argv[1] = script; // Release previous reply object. freeReplyObject(result); result = NULL; // Update stats. Lck_Lock(&db->mutex); db->stats.commands.noscript++; Lck_Unlock(&db->mutex); // Command execution is completed. } else { done = 1; } } // Send command, unless it was originally an EVAL command and it // was already executed using EVALSHA. if (!done) { result = get_redis_repy(ctx, context, timeout, argc, argv, asking); } // Log failed executions. if (result == NULL) { REDIS_LOG_ERROR(ctx, "Failed to execute command (error=%d, command=%s, db=%s, server=%s): %s", context->rcontext->err, argv[0], db->name, context->server->location.raw, HIREDIS_ERRSTR(context->rcontext, result)); } unlock: // Release context. unlock_redis_context(ctx, db, state, context); // Check WS fail flag. if (failed_ws) { *retries = max_retries; REDIS_FAIL_WS(ctx, NULL); } // Context not available. } else { REDIS_LOG_ERROR(ctx, "Failed to execute command (command=%s, db=%s): context not available", argv[0], db->name); } // Update stats. Lck_Lock(&db->mutex); if (*retries > 0) { db->stats.commands.retried++; } if (result == NULL) { db->stats.commands.failed++; } else { db->stats.commands.total++; } Lck_Unlock(&db->mutex); // Try again? if (result == NULL) { if (*retries < max_retries) { (*retries)++; } else { break; } } } // Execution plan not available. } else { *retries = max_retries; REDIS_LOG_ERROR(ctx, "Failed to execute command (command=%s, db=%s): execution plan not available", argv[0], db->name); } // Done! return result; } redis_server_t * unsafe_add_redis_server( VRT_CTX, struct vmod_redis_db *db, vcl_state_t *config, const char *location, enum REDIS_SERVER_ROLE role) { // Assertions. Lck_AssertHeld(&config->mutex); Lck_AssertHeld(&db->mutex); // Initializations. redis_server_t *result = NULL; // Look for a server matching the location. If found, remove if from the // list. It would be reinserted later, perhaps in a different list. for (unsigned iweight = 0; result == NULL && iweight < NREDIS_SERVER_WEIGHTS; iweight++) { for (enum REDIS_SERVER_ROLE irole = 0; result == NULL && irole < NREDIS_SERVER_ROLES; irole++) { redis_server_t *iserver; VTAILQ_FOREACH(iserver, &db->servers[iweight][irole], list) { CHECK_OBJ_NOTNULL(iserver, REDIS_SERVER_MAGIC); if (strcmp(iserver->location.raw, location) == 0) { VTAILQ_REMOVE(&db->servers[iweight][irole], iserver, list); result = iserver; break; } } } } // Create a new server instance? if (result == NULL) { // Create new instance. result = new_redis_server(db, location, role); if (result != NULL) { // If role is unknown try to discover it. This won't be retried. On // failures discovering the role the module will depend on other // discovery capabilities such as Redis Sentinel or Redis Cluster. if (result->role == REDIS_SERVER_TBD_ROLE) { result->role = unsafe_discover_redis_server_role(ctx, result); } // Calculate weight. if (result->location.type == REDIS_SERVER_LOCATION_HOST_TYPE) { struct in_addr ia4; if (inet_pton(AF_INET, result->location.parsed.address.host, &ia4)) { result->weight = NREDIS_SERVER_WEIGHTS - 1; subnet_t *isubnet; VTAILQ_FOREACH(isubnet, &config->subnets, list) { CHECK_OBJ_NOTNULL(isubnet, SUBNET_MAGIC); if ((ntohl(ia4.s_addr) & isubnet->mask.s_addr) == (isubnet->address.s_addr & isubnet->mask.s_addr)) { result->weight = isubnet->weight; break; } } } else { result->weight = NREDIS_SERVER_WEIGHTS - 1; } } else { result->weight = 0; } // Log event. REDIS_LOG_INFO(ctx, "New server registered (db=%s, server=%s, role=%d, weight=%d)", db->name, result->location.raw, result->role, result->weight); // Update stats. db->stats.servers.total++; } else { REDIS_LOG_ERROR(ctx, "Failed to register server (db=%s, server=%s)", db->name, location); db->stats.servers.failed++; } // Update existing server instance. } else { // If role is unknown try to discover it. This won't be retried. On // failures the module stays with the info it has so far. Discovery of // the real role will depend on other discovery capabilities such as // Redis Sentinel or Redis Cluster. if (role == REDIS_SERVER_TBD_ROLE) { enum REDIS_SERVER_ROLE r = unsafe_discover_redis_server_role(ctx, result); if (r != REDIS_SERVER_TBD_ROLE) { result->role = r; } } else { result->role = role; } // Flush the sickness flag. unsigned now = time(NULL); if (result->sickness.exp > now) { result->sickness.exp = now; } // Log event. REDIS_LOG_INFO(ctx, "Server updated (db=%s, server=%s, role=%d, weight=%d)", db->name, result->location.raw, result->role, result->weight); } // Do not continue if a server instance is not available. if (result != NULL) { // Register server instance in the right list. VTAILQ_INSERT_TAIL( &db->servers[result->weight][result->role], result, list); } // Done! return result; } /****************************************************************************** * UTILITIES. *****************************************************************************/ static redisContext * new_rcontext( VRT_CTX, redis_server_t * server, time_t now, unsigned ephemeral, unsigned dblocked) { // Assertions. if (dblocked) Lck_AssertHeld(&server->db->mutex); // Create context. redisContext *result; if ((server->db->connection_timeout.tv_sec > 0) || (server->db->connection_timeout.tv_usec > 0)) { switch (server->location.type) { case REDIS_SERVER_LOCATION_HOST_TYPE: result = redisConnectWithTimeout( server->location.parsed.address.host, server->location.parsed.address.port, server->db->connection_timeout); break; case REDIS_SERVER_LOCATION_SOCKET_TYPE: result = redisConnectUnixWithTimeout( server->location.parsed.path, server->db->connection_timeout); break; default: result = NULL; } } else { switch (server->location.type) { case REDIS_SERVER_LOCATION_HOST_TYPE: result = redisConnect( server->location.parsed.address.host, server->location.parsed.address.port); break; case REDIS_SERVER_LOCATION_SOCKET_TYPE: result = redisConnectUnix( server->location.parsed.path); break; default: result = NULL; } } AN(result); // Check created context. if (result->err) { REDIS_LOG_ERROR(ctx, "Failed to establish connection (error=%d, db=%s, server=%s): %s", result->err, server->db->name, server->location.raw, HIREDIS_ERRSTR(result)); redisFree(result); result = NULL; } // Optionally setup TLS & submit AUTH / HELLO command. if (result != NULL) { REDIS_BLESS_CONTEXT( ctx, result, server->db, "Failed to initialize connection", "db=%s, server=%s", server->db->name, server->location.raw); } // Update stats & sickness flag. if (!dblocked) Lck_Lock(&server->db->mutex); if (result != NULL) { if (server->sickness.exp > now) { server->sickness.exp = now; REDIS_LOG_INFO(ctx, "Server sickness tag cleared (db=%s, server=%s)", server->db->name, server->location.raw); } if (!ephemeral) { server->db->stats.connections.total++; } } else { if (server->db->sickness_ttl > 0) { server->sickness.tst = now; server->sickness.exp = now + server->db->sickness_ttl; REDIS_LOG_INFO(ctx, "Server sickness tag set (db=%s, server=%s)", server->db->name, server->location.raw); } if (!ephemeral) { server->db->stats.connections.failed++; } } if (!dblocked) Lck_Unlock(&server->db->mutex); #if HIREDIS_MAJOR >= 0 && HIREDIS_MINOR >= 12 // Enable TCP keep-alive. if ((result != NULL) && (server->location.type == REDIS_SERVER_LOCATION_HOST_TYPE)) { redisEnableKeepAlive(result); } #endif // Done! return result; } static enum REDIS_SERVER_ROLE unsafe_discover_redis_server_role(VRT_CTX, redis_server_t *server) { // Assertions. Lck_AssertHeld(&server->db->mutex); // Initializations. enum REDIS_SERVER_ROLE result = REDIS_SERVER_TBD_ROLE; // Create context. redisContext *rcontext = new_rcontext(ctx, server, time(NULL), 1, 1); if ((rcontext != NULL) && (!rcontext->err)) { // Set command execution timeout. int tr = redisSetTimeout(rcontext, server->db->command_timeout); if (tr != REDIS_OK) { REDIS_LOG_ERROR(ctx, "Failed to set role discovery command execution timeout (error=%d, db=%s, server=%s)", tr, server->db->name, server->location.raw); } // Send command. redisReply *reply = redisCommand(rcontext, ROLE_DISCOVERY_COMMAND); // Check reply. if ((!rcontext->err) && (reply != NULL) && (reply->type == REDIS_REPLY_ARRAY) && (reply->elements > 0) && (reply->element[0]->type == REDIS_REPLY_STRING)) { if (strcmp(reply->element[0]->str, "master") == 0) { result = REDIS_SERVER_MASTER_ROLE; } else if (strcmp(reply->element[0]->str, "slave") == 0) { result = REDIS_SERVER_SLAVE_ROLE; } if (result != REDIS_SERVER_TBD_ROLE) { REDIS_LOG_INFO(ctx, "Server role discovered (db=%s, server=%s, role=%d)", server->db->name, server->location.raw, result); } } else { REDIS_LOG_ERROR(ctx, "Failed to execute role discovery command (error=%d, db=%s, server=%s): %s", rcontext, server->db->name, server->location.raw, HIREDIS_ERRSTR(rcontext, reply)); } // Release reply. if (reply != NULL) { freeReplyObject(reply); } } else { if (rcontext != NULL) { REDIS_LOG_ERROR(ctx, "Failed to establish role discovery connection (error=%d, db=%s, server=%s): %s", rcontext->err, server->db->name, server->location.raw, HIREDIS_ERRSTR(rcontext)); } else { REDIS_LOG_ERROR(ctx, "Failed to establish role discovery connection (db=%s, server=%s)", server->db->name, server->location.raw); } } // Release context. if (rcontext != NULL) { redisFree(rcontext); } // Done! return result; } static unsigned is_valid_redis_context(redis_context_t *context, time_t now, unsigned dblocked) { // Assertions. if (dblocked) Lck_AssertHeld(&context->server->db->mutex); // Check if context is in an error state. if (context->rcontext->err) { if (!dblocked) Lck_Lock(&context->server->db->mutex); context->server->db->stats.connections.dropped.error++; if (!dblocked) Lck_Unlock(&context->server->db->mutex); return 0; } // Check if context is too old (version). if (context->version != vmod_state.version) { if (!dblocked) Lck_Lock(&context->server->db->mutex); context->server->db->stats.connections.dropped.version++; if (!dblocked) Lck_Unlock(&context->server->db->mutex); return 0; } // Check if context is too old (TTL). if ((context->server->db->connection_ttl > 0) && (now - context->tst > context->server->db->connection_ttl)) { if (!dblocked) Lck_Lock(&context->server->db->mutex); context->server->db->stats.connections.dropped.ttl++; if (!dblocked) Lck_Unlock(&context->server->db->mutex); return 0; } // Check if context was created before the server was flagged // as sick. if (context->server->db->sickness_ttl > 0) { unsigned sick = 0; if (!dblocked) Lck_Lock(&context->server->db->mutex); if (context->tst <= context->server->sickness.tst) { sick = 1; context->server->db->stats.connections.dropped.sick++; } if (!dblocked) Lck_Unlock(&context->server->db->mutex); if (sick) { return 0; } } // Check if context connection has been hung up by the server. struct pollfd fds; fds.fd = context->rcontext->fd; fds.events = POLLOUT; if ((poll(&fds, 1, 0) != 1) || (fds.revents & POLLHUP)) { if (!dblocked) Lck_Lock(&context->server->db->mutex); context->server->db->stats.connections.dropped.hung_up++; if (!dblocked) Lck_Unlock(&context->server->db->mutex); return 0; } // Valid! return 1; } static struct plan * new_execution_plan(VRT_CTX, struct vmod_redis_db *db) { struct plan *result = (void *)WS_Alloc(ctx->ws, sizeof(struct plan)); if (result == NULL) { REDIS_FAIL_WS(ctx, NULL); } result->contexts.n = 0; result->contexts.next = 0; result->contexts.list = NULL; result->servers.n = 0; result->servers.next = 0; result->servers.list = NULL; return result; } void populate_simple_execution_plan( VRT_CTX, struct plan *plan, struct vmod_redis_db *db, task_state_t *state, unsigned max_size, redis_server_t *server) { // Populate list of contexts? if (!db->shared_connections) { // Initializations. time_t now = time(NULL); unsigned free_ws = WS_ReserveAll(ctx->ws); unsigned used_ws = 0; plan->contexts.list = (redis_context_t **) WS_Reservation(ctx->ws); plan->contexts.n = 0; // Search for contexts matching the requested conditions. redis_context_t *icontext, *icontext_tmp; VTAILQ_FOREACH_SAFE(icontext, &state->contexts, list, icontext_tmp) { CHECK_OBJ_NOTNULL(icontext, REDIS_CONTEXT_MAGIC); if ((icontext->server->db == db) && (icontext->server == server)) { if (is_valid_redis_context(icontext, now, 0)) { if (free_ws >= sizeof(redis_context_t *)) { used_ws += sizeof(redis_context_t *); plan->contexts.list[plan->contexts.n++] = icontext; if (plan->contexts.n == max_size) { break; } } else { WS_Release(ctx->ws, 0); REDIS_FAIL_WS(ctx, ); } } else { VTAILQ_REMOVE(&state->contexts, icontext, list); state->ncontexts--; free_redis_context(icontext); } } } // Done! WS_Release(ctx->ws, used_ws); } // Build list of servers. unsigned free_ws = WS_ReserveAll(ctx->ws); if (free_ws >= sizeof(redis_server_t *)) { plan->servers.list = (redis_server_t **) WS_Reservation(ctx->ws); plan->servers.n = 1; plan->servers.list[0] = server; WS_Release(ctx->ws, sizeof(redis_server_t *)); } else { WS_Release(ctx->ws, 0); REDIS_FAIL_WS(ctx, ); } } void populate_execution_plan( VRT_CTX, struct plan *plan, struct vmod_redis_db *db, task_state_t *state, unsigned max_size, unsigned master, unsigned slot) { // Initializations. time_t now = time(NULL); // Populate list of contexts? if (!db->shared_connections) { // Initializations. unsigned free_ws = WS_ReserveAll(ctx->ws); unsigned used_ws = 0; plan->contexts.list = (redis_context_t **) WS_Reservation(ctx->ws); plan->contexts.n = 0; // Search for contexts matching the requested conditions. redis_context_t *icontext, *icontext_tmp; VTAILQ_FOREACH_SAFE(icontext, &state->contexts, list, icontext_tmp) { CHECK_OBJ_NOTNULL(icontext, REDIS_CONTEXT_MAGIC); if ((icontext->server->db == db) && ((master && (icontext->server->role == REDIS_SERVER_MASTER_ROLE)) || (!master && (icontext->server->role != REDIS_SERVER_MASTER_ROLE))) && ((!db->cluster.enabled) || (icontext->server->cluster.slots[slot]))) { if (is_valid_redis_context(icontext, now, 0)) { if (free_ws >= sizeof(redis_context_t *)) { used_ws += sizeof(redis_context_t *); plan->contexts.list[plan->contexts.n++] = icontext; if (plan->contexts.n == max_size) { break; } } else { WS_Release(ctx->ws, 0); REDIS_FAIL_WS(ctx, ); } } else { VTAILQ_REMOVE(&state->contexts, icontext, list); state->ncontexts--; free_redis_context(icontext); } } } // If some context was added to the execution plan, move it to the end // of the list. This ensures a nice distribution of load between all // available contexts. if (plan->contexts.n > 0) { VTAILQ_REMOVE(&state->contexts, plan->contexts.list[0], list); VTAILQ_INSERT_TAIL(&state->contexts, plan->contexts.list[0], list); } // Done! WS_Release(ctx->ws, used_ws); } // Populate list of servers? if (plan->contexts.n < max_size) { // Initializations. unsigned remaining = max_size - plan->contexts.n; unsigned free_ws = WS_ReserveAll(ctx->ws); unsigned used_ws = 0; plan->servers.list = (redis_server_t **) WS_Reservation(ctx->ws); plan->servers.n = 0; // Get database lock. Lck_Lock(&db->mutex); // Build list of servers. // - First round: // + Give higher priority to: // * Slave servers. // * Servers with lower weight. // + Skip servers not matching 'slot' if clustering is enabled. // + Skip sick servers. // + Skip slave & TBD servers if 'master' is set. // - Second round (only if clustering is disabled): // + Consider sick and TBD servers skipped during the first round. for (unsigned round = 1; round <= (db->cluster.enabled ? 1 : 2); round++) { for (unsigned iweight = 0; remaining > 0 && iweight < NREDIS_SERVER_WEIGHTS; iweight++) { for (enum REDIS_SERVER_ROLE irole = 0; remaining > 0 && irole < NREDIS_SERVER_ROLES; irole++) { if ((!master) || (((round == 1) && (irole == REDIS_SERVER_MASTER_ROLE)) || ((round == 2) && ((irole == REDIS_SERVER_MASTER_ROLE) || (irole == REDIS_SERVER_TBD_ROLE))))) { unsigned nservers = plan->servers.n; redis_server_t *iserver; VTAILQ_FOREACH(iserver, &db->servers[iweight][irole], list) { CHECK_OBJ_NOTNULL(iserver, REDIS_SERVER_MAGIC); assert(iserver->weight == iweight); assert(iserver->role == irole); if (((!db->cluster.enabled) || (iserver->cluster.slots[slot])) && (((round == 1) && (iserver->sickness.exp <= now)) || ((round == 2) && (((master) && (iserver->role == REDIS_SERVER_TBD_ROLE)) || (iserver->sickness.exp > now))))) { if (free_ws >= sizeof(redis_server_t *)) { used_ws += sizeof(redis_server_t *); plan->servers.list[plan->servers.n++] = iserver; if (--remaining == 0) { break; } } else { WS_Release(ctx->ws, 0); REDIS_FAIL_WS(ctx, ); } } } // If some server in this list was added to the // execution plan, move it to the end of the list. This // ensures a nice distribution of load between all // servers. if ((round == 1) && (nservers < plan->servers.n)) { VTAILQ_REMOVE( &db->servers[iweight][irole], plan->servers.list[nservers], list); VTAILQ_INSERT_TAIL( &db->servers[iweight][irole], plan->servers.list[nservers], list); } } } } } // Continue building list of servers. // - Only executed when clustering is enabled and if the execution // plan is still empty. Any server will be ok to get a redirection to // the right server and the trigger a discovery of the cluster // topology. // - Give higher priority to: // + Slave servers. // + Servers with lower weight. // - Skip sick servers during the third round. // - Skip healthy servers during the fourth round. if ((db->cluster.enabled) && (plan->servers.n == 0)) { for (unsigned round = 3; round <= 4; round++) { for (unsigned iweight = 0; remaining > 0 && iweight < NREDIS_SERVER_WEIGHTS; iweight++) { for (enum REDIS_SERVER_ROLE irole = 0; remaining > 0 && irole < NREDIS_SERVER_ROLES; irole++) { redis_server_t *iserver; VTAILQ_FOREACH(iserver, &db->servers[iweight][irole], list) { CHECK_OBJ_NOTNULL(iserver, REDIS_SERVER_MAGIC); assert(iserver->weight == iweight); assert(iserver->role == irole); if (((round == 3) && (iserver->sickness.exp <= now)) || ((round == 4) && (iserver->sickness.exp > now))) { if (free_ws >= sizeof(redis_server_t *)) { used_ws += sizeof(redis_server_t *); plan->servers.list[plan->servers.n++] = iserver; if (--remaining == 0) { break; } } else { WS_Release(ctx->ws, 0); REDIS_FAIL_WS(ctx, ); } } } } } } } // Release database lock. Lck_Unlock(&db->mutex); // Done! WS_Release(ctx->ws, used_ws); } } static struct plan * plan_execution( VRT_CTX, struct vmod_redis_db *db, task_state_t *state, unsigned max_size, redis_server_t *server, unsigned master, unsigned slot) { // Initializations. struct plan *result = new_execution_plan(ctx, db); // Do not continue if something failed while creating an empty execution // plan. if (result != NULL) { if (server != NULL) { populate_simple_execution_plan(ctx, result, db, state, max_size, server); } else { populate_execution_plan(ctx, result, db, state, max_size, master, slot); } } // Done! return result; } static redis_context_t * lock_private_redis_context( VRT_CTX, struct vmod_redis_db *db, task_state_t *state, struct plan *plan) { // Initializations. redis_context_t *result = NULL; // Is there any context in the execution plan? if (plan->contexts.next < plan->contexts.n) { result = plan->contexts.list[plan->contexts.next++]; // No contexts in the execution plan. Create new context according with // the execution plan. If any error arises discard the context and continue. } else { // Initializations. time_t now = time(NULL); // Select next server in the execution plan. assert(plan->servers.next < plan->servers.n); redis_server_t *server = plan->servers.list[plan->servers.next]; plan->servers.next = (plan->servers.next + 1) % plan->servers.n; // If an empty slot is not available, release an existing context. if (state->ncontexts >= db->max_connections) { redis_context_t *context = VTAILQ_FIRST(&state->contexts); CHECK_OBJ_NOTNULL(context, REDIS_CONTEXT_MAGIC); VTAILQ_REMOVE(&state->contexts, context, list); state->ncontexts--; free_redis_context(context); Lck_Lock(&db->mutex); db->stats.connections.dropped.overflow++; Lck_Unlock(&db->mutex); } // Create new context using the previously selected server. If any // error arises discard the context and return. redisContext *rcontext = new_rcontext(ctx, server, now, 0, 0); if (rcontext != NULL) { result = new_redis_context(server, rcontext, now); VTAILQ_INSERT_TAIL(&state->contexts, result, list); state->ncontexts++; } } // Done! return result; } static redis_context_t * lock_shared_redis_context( VRT_CTX, struct vmod_redis_db *db, task_state_t *state, struct plan *plan) { // Initializations. redis_context_t *result = NULL; time_t now = time(NULL); // Select next server in the execution plan. assert(plan->servers.next < plan->servers.n); redis_server_t *server = plan->servers.list[plan->servers.next]; plan->servers.next = (plan->servers.next + 1) % plan->servers.n; // Get database lock. Lck_Lock(&server->db->mutex); retry: // Look for an existing free context. while (!VTAILQ_EMPTY(&server->pool.free_contexts)) { // Extract context. result = VTAILQ_FIRST(&server->pool.free_contexts); CHECK_OBJ_NOTNULL(result, REDIS_CONTEXT_MAGIC); // Mark the context as busy. VTAILQ_REMOVE(&server->pool.free_contexts, result, list); VTAILQ_INSERT_TAIL(&server->pool.busy_contexts, result, list); // Is the context valid? if (!is_valid_redis_context(result, now, 1)) { // Release context. VTAILQ_REMOVE(&server->pool.busy_contexts, result, list); server->pool.ncontexts--; free_redis_context(result); // A new context needs to be selected. result = NULL; // A valid free context was found. } else { break; } } // If required, create new context using the currently selected server. If any // error arises discard the context and continue. If maximum number of contexts // has been reached, wait for another thread releasing some context. if (result == NULL) { // If an no more contexts can be created, wait for another thread. if (server->pool.ncontexts >= db->max_connections) { Lck_CondWait(&server->pool.cond, &server->db->mutex); db->stats.workers.blocked++; goto retry; } // Create new context using the previously selected server. If any // error arises discard the context and return. redisContext *rcontext = new_rcontext(ctx, server, now, 0, 1); if (rcontext != NULL) { result = new_redis_context(server, rcontext, now); VTAILQ_INSERT_TAIL(&server->pool.busy_contexts, result, list); server->pool.ncontexts++; } } // Release database lock. Lck_Unlock(&server->db->mutex); // Done! return result; } static redis_context_t * lock_redis_context( VRT_CTX, struct vmod_redis_db *db, task_state_t *state, struct plan *plan) { if (db->shared_connections) { return lock_shared_redis_context(ctx, db, state, plan); } else { return lock_private_redis_context(ctx, db, state, plan); } } static void unlock_shared_redis_context( VRT_CTX, struct vmod_redis_db *db, redis_context_t *context) { // Assertions. CHECK_OBJ_NOTNULL(context, REDIS_CONTEXT_MAGIC); CHECK_OBJ_NOTNULL(context->server, REDIS_SERVER_MAGIC); // Return context to the pool's free list. Lck_Lock(&context->server->db->mutex); VTAILQ_REMOVE(&context->server->pool.busy_contexts, context, list); VTAILQ_INSERT_TAIL(&context->server->pool.free_contexts, context, list); AZ(pthread_cond_signal(&context->server->pool.cond)); Lck_Unlock(&context->server->db->mutex); } static void unlock_redis_context( VRT_CTX, struct vmod_redis_db *db, task_state_t *state, redis_context_t *context) { if (db->shared_connections) { return unlock_shared_redis_context(ctx, db, context); } } static redisReply * get_redis_repy( VRT_CTX, redis_context_t *context, struct timeval timeout, unsigned argc, const char *argv[], unsigned asking) { // Initializations. redisReply *result = NULL; redisReply *reply; unsigned readonly = ((context->server->db->cluster.enabled) && (context->server->role == REDIS_SERVER_SLAVE_ROLE)); // Set command execution timeout. int tr = redisSetTimeout(context->rcontext, timeout); if (tr != REDIS_OK) { REDIS_LOG_ERROR(ctx, "Failed to set command execution timeout (error=%d, db=%s, server=%s)", tr, context->server->db->name, context->server->location.raw); } // Build pipeline. if (readonly) { redisAppendCommand(context->rcontext, "READONLY"); } if (asking) { redisAppendCommand(context->rcontext, "ASKING"); } redisAppendCommandArgv(context->rcontext, argc, argv, NULL); if (readonly) { redisAppendCommand(context->rcontext, "READWRITE"); } // Fetch READONLY command reply? if (readonly) { reply = NULL; redisGetReply(context->rcontext, (void **)&reply); if (reply != NULL) { freeReplyObject(reply); } } // Fetch ASKING command reply. if (asking) { reply = NULL; redisGetReply(context->rcontext, (void **)&reply); if (reply != NULL) { freeReplyObject(reply); } } // Fetch command reply. redisGetReply(context->rcontext, (void **)&result); // Fetch READWRITE command reply? if (readonly) { reply = NULL; redisGetReply(context->rcontext, (void **)&reply); if (reply != NULL) { freeReplyObject(reply); } } // Done! return result; } static const char * sha1(VRT_CTX, const char *script) { // Hash. unsigned char buffer[20]; SHA1_CTX sha1_ctx; SHA1Init(&sha1_ctx); SHA1Update(&sha1_ctx, (const unsigned char *) script, strlen(script)); SHA1Final(buffer, &sha1_ctx); // Encode. char *result = WS_Alloc(ctx->ws, 41);; if (result == NULL) { return NULL; } char *ptr = result; for (int i = 0; i < 20; i++) { sprintf(ptr, "%02x", buffer[i]); ptr += 2; } // Done! return result; } libvmod-redis-21.0/src/core.h000066400000000000000000000375021476735432100161070ustar00rootroot00000000000000#ifndef CORE_H_INCLUDED #define CORE_H_INCLUDED #include #include #include #ifdef TLS_ENABLED #include #endif #include #include #include "vqueue.h" #define NREDIS_SERVER_ROLES 3 #define NREDIS_SERVER_WEIGHTS 4 #define NREDIS_CLUSTER_SLOTS 16384 enum REDIS_PROTOCOL { REDIS_PROTOCOL_DEFAULT = 0, REDIS_PROTOCOL_RESP2 = 2, REDIS_PROTOCOL_RESP3 = 3 }; // Required lock ordering to avoid deadlocks: // 1. vcl_state->mutex. // 2. vmod_redis_db->mutex. // WARNING: ordering of roles in this enumeration is relevant when populating // an execution plan. enum REDIS_SERVER_ROLE { REDIS_SERVER_SLAVE_ROLE = 0, REDIS_SERVER_MASTER_ROLE = 1, REDIS_SERVER_TBD_ROLE = 2 }; enum REDIS_SERVER_LOCATION_TYPE { REDIS_SERVER_LOCATION_HOST_TYPE, REDIS_SERVER_LOCATION_SOCKET_TYPE }; typedef struct redis_server { // Object marker. #define REDIS_SERVER_MAGIC 0xac587b11 unsigned magic; // Database. struct vmod_redis_db *db; // Location (allocated in the heap). struct { const char *raw; enum REDIS_SERVER_LOCATION_TYPE type; union { struct { const char *host; unsigned port; } address; const char *path; } parsed; } location; // Role (rw field to be protected by db->mutex). enum REDIS_SERVER_ROLE role; // Weight. unsigned weight; // Shared pool. struct { // Condition variable. pthread_cond_t cond; // Contexts (rw fields -allocated in the heap- to be protected by // db->mutex and the associated condition variable). unsigned ncontexts; VTAILQ_HEAD(,redis_context) free_contexts; VTAILQ_HEAD(,redis_context) busy_contexts; } pool; // Redis Cluster state (rw fields to be protected by db->mutex). struct { unsigned slots[NREDIS_CLUSTER_SLOTS]; } cluster; // Sickness timestamps (rw fields to be protected by db->mutex): last time // the server was flagged as sick, and expiration of the last sickness // condition. struct { time_t tst; time_t exp; } sickness; // Tail queue. VTAILQ_ENTRY(redis_server) list; } redis_server_t; typedef struct redis_context { // Object marker. #define REDIS_CONTEXT_MAGIC 0xe11eaa70 unsigned magic; // Server. redis_server_t *server; // Data (allocated in the heap). redisContext *rcontext; unsigned version; time_t tst; // Tail queue. VTAILQ_ENTRY(redis_context) list; } redis_context_t; struct vcl_state; typedef struct vcl_state vcl_state_t; struct vmod_redis_db { // Object marker. unsigned magic; #define VMOD_REDIS_DATABASE_MAGIC 0xef35182b // Mutex. struct lock mutex; // Configuration. // XXX: required because PRIV_VCL pointers are not available when the // VMOD releases database instances. This should be fixed in future // Varnish releases. vcl_state_t *config; // General options (allocated in the heap). const char *name; struct timeval connection_timeout; unsigned connection_ttl; struct timeval command_timeout; unsigned max_command_retries; unsigned shared_connections; unsigned max_connections; enum REDIS_PROTOCOL protocol; #ifdef TLS_ENABLED redisSSLContext *tls_ssl_ctx; #endif const char *user; const char *password; time_t sickness_ttl; unsigned ignore_slaves; // Redis servers (rw field -allocated in the heap- to be protected by the // associated mutex), clustered by weight & role. VTAILQ_HEAD(,redis_server) servers[NREDIS_SERVER_WEIGHTS][NREDIS_SERVER_ROLES]; // Redis Cluster options. struct { unsigned enabled; unsigned max_hops; } cluster; // Stats (rw fields to be protected by the associated mutex). struct stats { struct { // Number of successfully created servers. uint64_t total; // Number of failures while trying to create new servers. uint64_t failed; } servers; struct { // Number of successfully created connections. uint64_t total; // Number of failures while trying to create new connections. uint64_t failed; // Number of (established and probably healthy) connections dropped. struct { uint64_t error; uint64_t hung_up; uint64_t overflow; uint64_t ttl; uint64_t version; uint64_t sick; } dropped; } connections; struct { // Number of times some worker thread have been blocked waiting for // a free connection. uint64_t blocked; } workers; struct { // Number of successfully executed commands (this includes Redis // error replies). uint64_t total; // Number of failed command executions (this does not include Redis // error replies). If retries have been requested, each failed try // is considered as a separate command. uint64_t failed; // Number of retried command executions (this includes both // successful and failed executions). uint64_t retried; // Number of successfully executed commands returning a Redis error // reply. uint64_t error; // Number of NOSCRIPT error replies while executing EVALSHA // commands. uint64_t noscript; } commands; struct { struct { // Number of successfully executed discoveries. uint64_t total; // Number of failed discoveries (this includes connection // failures, unexpected responses, etc.). uint64_t failed; } discoveries; struct { // Number of MOVED replies. uint64_t moved; // Number of ASK replies. uint64_t ask; } replies; } cluster; } stats; }; typedef struct task_state { // Object marker. #define TASK_STATE_MAGIC 0xa6bc103e unsigned magic; // Private contexts (allocated in the heap). unsigned ncontexts; VTAILQ_HEAD(,redis_context) contexts; // Current database. struct vmod_redis_db *db; // Redis command: // - Database. // - Arguments (allocated in the session workspace). // - Reply (allocated in the heap). #define MAX_REDIS_COMMAND_ARGS 128 struct { struct vmod_redis_db *db; struct timeval timeout; unsigned max_retries; unsigned argc; const char *argv[MAX_REDIS_COMMAND_ARGS]; redisReply *reply; } command; } task_state_t; typedef struct subnet { // Object marker. #define SUBNET_MAGIC 0x27facd57 unsigned magic; // Weight. unsigned weight; // Address and mask stored in unsigned 32 bit variables (in_addr.s_addr) // using host byte oder. // XXX: only IPv4 subnets supported. struct in_addr address; struct in_addr mask; // Tail queue. VTAILQ_ENTRY(subnet) list; } subnet_t; typedef struct database { // Object marker. #define DATABASE_MAGIC 0x9200fda1 unsigned magic; // Database. struct vmod_redis_db *db; // Tail queue. VTAILQ_ENTRY(database) list; } database_t; struct vcl_state { // Object marker. #define VCL_STATE_MAGIC 0x77feec11 unsigned magic; // Mutex. struct lock mutex; // Subnets (rw field to be protected by the associated mutex). VTAILQ_HEAD(,subnet) subnets; // Databases (rw field to be protected by the associated mutex). VTAILQ_HEAD(,database) dbs; // Sentinel (rw fields to be protected by the associated mutex). struct { // Raw configuration. const char *locations; unsigned period; struct timeval connection_timeout; struct timeval command_timeout; enum REDIS_PROTOCOL protocol; #ifdef TLS_ENABLED unsigned tls; const char *tls_cafile; const char *tls_capath; const char *tls_certfile; const char *tls_keyfile; const char *tls_sni; #endif const char *password; // Thread reference + shared state. pthread_t thread; unsigned active; unsigned discovery; } sentinels; }; typedef struct vmod_state { // Mutex. pthread_mutex_t mutex; // Version increased on every VCL warm event (rw field protected by the // associated mutex on writes; it's ok to ignore the lock during reads). // This will be used to (1) reestablish connections binded to worker // threads; and (2) regenerate pooled connections shared between threads. unsigned version; // Varnish locks. struct { unsigned refs; struct vsc_seg *vsc_seg; struct VSC_lck *config; struct VSC_lck *db; } locks; } vmod_state_t; extern vmod_state_t vmod_state; // See: https://stackoverflow.com/a/8814003/1806102. #define HIREDIS_ERRSTR_1(rcontext) \ (rcontext->err ? rcontext->errstr : "-") #define HIREDIS_ERRSTR_2(rcontext, reply) \ (rcontext->err ? \ rcontext->errstr : \ ((reply != NULL && \ (reply->type == REDIS_REPLY_ERROR || \ reply->type == REDIS_REPLY_STATUS || \ reply->type == REDIS_REPLY_STRING)) ? reply->str : "-")) #define HIREDIS_ERRSTR_X(x, rcontext, reply, FUNC, ...) FUNC #define HIREDIS_ERRSTR(...) \ HIREDIS_ERRSTR_X(,##__VA_ARGS__, \ HIREDIS_ERRSTR_2(__VA_ARGS__), \ HIREDIS_ERRSTR_1(__VA_ARGS__)) #if HIREDIS_MAJOR >= 1 && HIREDIS_MINOR >= 0 #define RESP3_ENABLED 1 #define RESP3_SWITCH(a, b) a #else #define RESP3_SWITCH(a, b) b #endif #define REDIS_LOG(ctx, priority, fmt, ...) \ do { \ const struct vrt_ctx *_ctx = ctx; \ \ char *_buffer; \ if (priority <= LOG_ERR) { \ assert(asprintf( \ &_buffer, \ "[REDIS][%s:%d] %s", __func__, __LINE__, fmt) > 0); \ } else { \ assert(asprintf( \ &_buffer, \ "[REDIS] %s", fmt) > 0); \ } \ \ syslog(priority, _buffer, ##__VA_ARGS__); \ \ unsigned _tag; \ if (priority <= LOG_ERR) { \ _tag = SLT_VCL_Error; \ } else { \ _tag = SLT_VCL_Log; \ } \ if ((_ctx != NULL) && (_ctx->vsl != NULL)) { \ VSLb(_ctx->vsl, _tag, _buffer, ##__VA_ARGS__); \ } else { \ VSL(_tag, NO_VXID, _buffer, ##__VA_ARGS__); \ } \ \ free(_buffer); \ } while (0) #define REDIS_LOG_ERROR(ctx, fmt, ...) \ REDIS_LOG(ctx, LOG_ERR, fmt, ##__VA_ARGS__) #define REDIS_LOG_WARNING(ctx, fmt, ...) \ REDIS_LOG(ctx, LOG_WARNING, fmt, ##__VA_ARGS__) #define REDIS_LOG_INFO(ctx, fmt, ...) \ REDIS_LOG(ctx, LOG_INFO, fmt, ##__VA_ARGS__) #define REDIS_FAIL(ctx, result, fmt, ...) \ do { \ syslog(LOG_ALERT, "[REDIS][%s:%d] " fmt, __func__, __LINE__, ##__VA_ARGS__); \ VRT_fail(ctx, "[REDIS][%s:%d] " fmt, __func__, __LINE__, ##__VA_ARGS__); \ return result; \ } while (0) #define REDIS_FAIL_WS(ctx, result) \ REDIS_FAIL(ctx, result, "Workspace overflow") #define REDIS_FAIL_INSTANCE(ctx, result) \ REDIS_FAIL(ctx, result, "Failed to create instance") #ifdef TLS_ENABLED #define REDIS_TLS(ctx, rcontext, db, message1, message2, ...) \ do { \ if (db->tls_ssl_ctx != NULL && \ redisInitiateSSLWithContext(rcontext, db->tls_ssl_ctx) != REDIS_OK) { \ REDIS_LOG_ERROR(ctx, \ message1 " (error=%d, " message2 "): %s", \ rcontext->err, ##__VA_ARGS__, HIREDIS_ERRSTR(rcontext)); \ redisFree(rcontext); \ rcontext = NULL; \ } \ } while (0) #else #define REDIS_TLS(ctx, rcontext, db, message1, message2, ...) #endif #define REDIS_BLESS_CONTEXT(ctx, rcontext, db, message1, message2, ...) \ do { \ REDIS_TLS(ctx, rcontext, db, message1, message2, ##__VA_ARGS__); \ \ if (rcontext != NULL) { \ redisReply *reply = NULL; \ \ if (db->protocol == REDIS_PROTOCOL_DEFAULT) { \ if (db->password != NULL) { \ if (db->user != NULL) { \ reply = redisCommand(rcontext, "AUTH %s %s", db->user, db->password); \ } else { \ reply = redisCommand(rcontext, "AUTH %s", db->password); \ } \ \ if ((rcontext->err) || \ (reply == NULL) || \ (reply->type != REDIS_REPLY_STATUS) || \ (strcmp(reply->str, "OK") != 0)) { \ REDIS_LOG_ERROR(ctx, \ message1 " (error=%d, " message2 "): %s", \ rcontext->err, ##__VA_ARGS__, HIREDIS_ERRSTR(rcontext, reply)); \ redisFree(rcontext); \ rcontext = NULL; \ } \ } \ } else { \ if (db->password != NULL) { \ reply = redisCommand(rcontext, "HELLO %d AUTH %s %s", \ db->protocol, (db->user != NULL) ? db->user : "default", db->password); \ } else { \ reply = redisCommand(rcontext, "HELLO %d", db->protocol); \ } \ \ if ((rcontext->err) || \ (reply == NULL) || \ (reply->type != REDIS_REPLY_ARRAY && \ RESP3_SWITCH(reply->type != REDIS_REPLY_MAP, 1)) \ ) { \ REDIS_LOG_ERROR(ctx, \ message1 " (error=%d, " message2 "): %s", \ rcontext->err, ##__VA_ARGS__, HIREDIS_ERRSTR(rcontext, reply)); \ redisFree(rcontext); \ rcontext = NULL; \ } \ } \ \ if (reply != NULL) { \ freeReplyObject(reply); \ } \ } \ } while (0) redis_server_t *new_redis_server( struct vmod_redis_db *db, const char *location, enum REDIS_SERVER_ROLE role); void free_redis_server(redis_server_t *server); redis_context_t *new_redis_context( redis_server_t *server, redisContext *rcontext, time_t tst); void free_redis_context(redis_context_t *context); struct vmod_redis_db *new_vmod_redis_db( vcl_state_t *config, const char *name, struct timeval connection_timeout, unsigned connection_ttl, struct timeval command_timeout, unsigned max_command_retries, unsigned shared_connections, unsigned max_connections, enum REDIS_PROTOCOL protocol, #ifdef TLS_ENABLED redisSSLContext *tls_ssl_ctx, #endif const char *user, const char *password, unsigned sickness_ttl, unsigned ignore_slaves, unsigned clustered, unsigned max_cluster_hops); void free_vmod_redis_db(struct vmod_redis_db *db); task_state_t *new_task_state(); void free_task_state(task_state_t *state); vcl_state_t *new_vcl_state(); void free_vcl_state(vcl_state_t *priv); subnet_t *new_subnet(unsigned weight, struct in_addr ia4, unsigned bits); void free_subnet(subnet_t *subnet); database_t *new_database(struct vmod_redis_db *db); void free_database(database_t *db); redisReply *redis_execute( VRT_CTX, struct vmod_redis_db *db, task_state_t *state, struct timeval timeout, unsigned max_retries, unsigned argc, const char *argv[], unsigned *retries, redis_server_t *server, unsigned asking, unsigned master, unsigned slot); redis_server_t * unsafe_add_redis_server( VRT_CTX, struct vmod_redis_db *db, vcl_state_t *config, const char *location, enum REDIS_SERVER_ROLE role); #endif libvmod-redis-21.0/src/crc16.c000066400000000000000000000106211476735432100160610ustar00rootroot00000000000000#include "config.h" /* * Copyright 2001-2010 Georges Menie (www.menie.org) * Copyright 2010-2012 Salvatore Sanfilippo (adapted to Redis coding style) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * 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 AND 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. */ /* CRC16 implementation according to CCITT standards. * * Note by @antirez: this is actually the XMODEM CRC 16 algorithm, using the * following parameters: * * Name : "XMODEM", also known as "ZMODEM", "CRC-16/ACORN" * Width : 16 bit * Poly : 1021 (That is actually x^16 + x^12 + x^5 + 1) * Initialization : 0000 * Reflect Input byte : False * Reflect Output CRC : False * Xor constant to output CRC : 0000 * Output for "123456789" : 31C3 */ #include "crc16.h" static const uint16_t crc16tab[256]= { 0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7, 0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef, 0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6, 0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de, 0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485, 0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d, 0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4, 0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc, 0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823, 0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b, 0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12, 0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a, 0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41, 0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49, 0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70, 0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78, 0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f, 0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067, 0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e, 0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256, 0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d, 0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405, 0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c, 0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634, 0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab, 0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3, 0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a, 0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92, 0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9, 0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1, 0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8, 0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0 }; uint16_t crc16(const char *buf, int len) { int counter; uint16_t crc = 0; for (counter = 0; counter < len; counter++) crc = (crc<<8) ^ crc16tab[((crc>>8) ^ *buf++)&0x00FF]; return crc; } libvmod-redis-21.0/src/crc16.h000066400000000000000000000001721476735432100160660ustar00rootroot00000000000000#ifndef CRC16_H_INCLUDED #define CRC16_H_INCLUDED #include uint16_t crc16(const char *buf, int len); #endif libvmod-redis-21.0/src/sentinel.c000066400000000000000000001116121476735432100167660ustar00rootroot00000000000000#include "config.h" #include #include #include #include #include #include #include #include #ifdef TLS_ENABLED #include #endif #include #include #include #include "cache/cache.h" #include "core.h" #include "sentinel.h" #define SUBSCRIPTION_COMMAND "PSUBSCRIBE +sdown -sdown +odown -odown +switch-master" struct server { // Object marker. #define SERVER_MAGIC 0x762a900c unsigned magic; // Location. const char *host; unsigned port; // Most recent discovered properties. enum REDIS_SERVER_ROLE role; unsigned down; // Sentinel responsible of the last change to the previous properties. struct sentinel *sentinel; // Tail queue. VTAILQ_ENTRY(server) list; }; struct sentinel { // Object marker. #define SENTINEL_MAGIC 0x8fefa255 unsigned magic; // Location. const char *host; unsigned port; // Non-blocking connection. redisAsyncContext *context; // State reference, useful when processing Pub/Sub messages. struct state *state; // Tail queue. VTAILQ_ENTRY(sentinel) list; }; struct state { // Object marker. #define STATE_MAGIC 0xd5ae987b unsigned magic; // Config reference. vcl_state_t *config; // Configuration. VTAILQ_HEAD(,sentinel) sentinels; unsigned period; struct timeval connection_timeout; struct timeval command_timeout; enum REDIS_PROTOCOL protocol; #ifdef TLS_ENABLED redisSSLContext *tls_ssl_ctx; #endif const char *password; // Timestamps. time_t last_change; time_t next_discovery; // Known servers. VTAILQ_HEAD(,server) servers; }; static void *sentinel_loop(void *object); static struct state *new_state( vcl_state_t *config, unsigned period, struct timeval connection_timeout, struct timeval command_timeout, enum REDIS_PROTOCOL protocol, #ifdef TLS_ENABLED redisSSLContext *tls_ssl_ctx, #endif const char *password); static void free_state(struct state *state); static void unsafe_set_locations(struct state *state, const char *locations); static void parse_sentinel_notification(struct sentinel *sentinel, redisReply *reply); static void discover_servers(struct state *state); static void unsafe_update_dbs(struct state *state); void unsafe_sentinel_start(vcl_state_t *config) { // Assertions. Lck_AssertHeld(&config->mutex); AN(config->sentinels.locations); AZ(config->sentinels.thread); AZ(config->sentinels.active); #ifdef TLS_ENABLED // Create Redis SSL context. redisSSLContext *tls_ssl_ctx = NULL; if (config->sentinels.tls) { redisSSLContextError ssl_error; tls_ssl_ctx = redisCreateSSLContext( config->sentinels.tls_cafile, config->sentinels.tls_capath, config->sentinels.tls_certfile, config->sentinels.tls_keyfile, config->sentinels.tls_sni, &ssl_error); if (tls_ssl_ctx == NULL) { REDIS_LOG_ERROR(NULL, "Failed to create SSL context: %s", redisSSLContextGetError(ssl_error)); return; } } #endif // Try to start new thread and launch initial proactive discovery. struct state *state = new_state( config, config->sentinels.period, config->sentinels.connection_timeout, config->sentinels.command_timeout, config->sentinels.protocol, #ifdef TLS_ENABLED tls_ssl_ctx, #endif config->sentinels.password); unsafe_set_locations(state, config->sentinels.locations); if (!VTAILQ_EMPTY(&state->sentinels)) { AZ(pthread_create( &config->sentinels.thread, NULL, &sentinel_loop, state)); config->sentinels.active = 1; config->sentinels.discovery = 1; } else { free_state(state); } } void unsafe_sentinel_discovery(vcl_state_t *config) { // Assertions. Lck_AssertHeld(&config->mutex); AN(config->sentinels.locations); AN(config->sentinels.thread); AN(config->sentinels.active); // Request proactive discovery. config->sentinels.discovery = 1; } void unsafe_sentinel_stop(vcl_state_t *config) { // Assertions. Lck_AssertHeld(&config->mutex); AN(config->sentinels.locations); AN(config->sentinels.thread); AN(config->sentinels.active); // Request thread stop. Caller must wait for thread termination outside // the config mutex lock in order to ensure the thread does not loose // the config reference in its internal state unexpectedly. config->sentinels.active = 0; } /****************************************************************************** * THREAD LOOP. *****************************************************************************/ static void connectCallback(const redisAsyncContext *context, int status) { if (status != REDIS_OK) { struct sentinel *sentinel; CAST_OBJ_NOTNULL(sentinel, context->data, SENTINEL_MAGIC); sentinel->context = NULL; REDIS_LOG_ERROR(NULL, "Failed to establish Sentinel connection (error=%d, status=%d, sentinel=%s:%d): %s", context->err, status, sentinel->host, sentinel->port, HIREDIS_ERRSTR(context)); } } static void disconnectCallback(const redisAsyncContext *context, int status) { struct sentinel *sentinel; CAST_OBJ_NOTNULL(sentinel, context->data, SENTINEL_MAGIC); sentinel->context = NULL; if (status != REDIS_OK) { REDIS_LOG_ERROR(NULL, "Sentinel connection lost (error=%d, status=%d, sentinel=%s:%d): %s", context->err, status, sentinel->host, sentinel->port, HIREDIS_ERRSTR(context)); } } static void authorizeCallback(redisAsyncContext *context, void *r, void *s) { redisReply *reply = r; struct sentinel *sentinel; CAST_OBJ_NOTNULL(sentinel, s, SENTINEL_MAGIC); if (reply == NULL || reply->type != REDIS_REPLY_STATUS || strcmp(reply->str, "OK") != 0) { REDIS_LOG_ERROR(NULL, "Failed to authenticate Sentinel connection (error=%d, sentinel=%s:%d): %s", context->err, sentinel->host, sentinel->port, HIREDIS_ERRSTR(context, reply)); } } static void helloCallback(redisAsyncContext *context, void *r, void *s) { redisReply *reply = r; struct sentinel *sentinel; CAST_OBJ_NOTNULL(sentinel, s, SENTINEL_MAGIC); if (reply == NULL || (reply->type != REDIS_REPLY_ARRAY && RESP3_SWITCH(reply->type != REDIS_REPLY_MAP, 1))) { REDIS_LOG_ERROR(NULL, "Failed to negotiate protocol in Sentinel connection (error=%d, sentinel=%s:%d): %s", context->err, sentinel->host, sentinel->port, HIREDIS_ERRSTR(context, reply)); } } static void subscribeCallback(redisAsyncContext *context, void *reply, void *s) { struct sentinel *sentinel; CAST_OBJ_NOTNULL(sentinel, s, SENTINEL_MAGIC); parse_sentinel_notification(sentinel, reply); } static void * sentinel_loop(void *object) { // Assertions. struct state *state; CAST_OBJ_NOTNULL(state, object, STATE_MAGIC); CHECK_OBJ_NOTNULL(state->config, VCL_STATE_MAGIC); // Log event. Lck_Lock(&state->config->mutex); REDIS_LOG_INFO(NULL, "Sentinel thread started (locations=%s, period=%d)", state->config->sentinels.locations, state->config->sentinels.period); Lck_Unlock(&state->config->mutex); // Initializations. struct ev_loop* loop = ev_loop_new(EVFLAG_AUTO); AN(loop); // Thread loop. while (1) { // Assertions. CHECK_OBJ_NOTNULL(state, STATE_MAGIC); CHECK_OBJ_NOTNULL(state->config, VCL_STATE_MAGIC); // Terminate the thread loop? Lck_Lock(&state->config->mutex); if (!state->config->sentinels.active) { Lck_Unlock(&state->config->mutex); break; } // Initializations. time_t now = time(NULL); // Is time to execute a new discovery? if ((state->config->sentinels.discovery) || ((state->period > 0) && (state->next_discovery <= now))) { Lck_Unlock(&state->config->mutex); discover_servers(state); Lck_Lock(&state->config->mutex); state->next_discovery = now + state->period; } // Terminate the thread loop? if (!state->config->sentinels.active) { Lck_Unlock(&state->config->mutex); break; } Lck_Unlock(&state->config->mutex); // Check Pub/Sub connections. struct sentinel *isentinel; VTAILQ_FOREACH(isentinel, &state->sentinels, list) { CHECK_OBJ_NOTNULL(isentinel, SENTINEL_MAGIC); if (isentinel->context == NULL) { isentinel->context = redisAsyncConnect(isentinel->host, isentinel->port); if ((isentinel->context != NULL) && (!isentinel->context->err)) { #ifdef TLS_ENABLED if (state->tls_ssl_ctx != NULL && redisInitiateSSLWithContext(&isentinel->context->c, state->tls_ssl_ctx) != REDIS_OK) { REDIS_LOG_ERROR(NULL, "Failed to secure asynchronous Sentinel connection (error=%d, sentinel=%s:%d): %s", isentinel->context->c.err, isentinel->host, isentinel->port, HIREDIS_ERRSTR((&isentinel->context->c))); redisAsyncFree(isentinel->context); isentinel->context = NULL; } #endif if (isentinel->context != NULL) { isentinel->context->data = isentinel; redisLibevAttach(loop, isentinel->context); redisAsyncSetConnectCallback(isentinel->context, connectCallback); redisAsyncSetDisconnectCallback(isentinel->context, disconnectCallback); if (state->password != NULL) { if (redisAsyncCommand( isentinel->context, authorizeCallback, isentinel, "AUTH %s", state->password) != REDIS_OK) { REDIS_LOG_ERROR(NULL, "Failed to enqueue asynchronous Sentinel AUTH command (error=%d, sentinel=%s:%d): %s", isentinel->context->err, isentinel->host, isentinel->port, HIREDIS_ERRSTR(isentinel->context)); redisAsyncFree(isentinel->context); isentinel->context = NULL; } } } if (isentinel->context != NULL) { if (state->protocol != REDIS_PROTOCOL_DEFAULT) { if (redisAsyncCommand( isentinel->context, helloCallback, isentinel, "HELLO %d", state->protocol) != REDIS_OK) { REDIS_LOG_ERROR(NULL, "Failed to enqueue asynchronous Sentinel HELLO command (error=%d, sentinel=%s:%d): %s", isentinel->context->err, isentinel->host, isentinel->port, HIREDIS_ERRSTR(isentinel->context)); redisAsyncFree(isentinel->context); isentinel->context = NULL; } } } if (isentinel->context != NULL) { if (redisAsyncCommand( isentinel->context, subscribeCallback, isentinel, SUBSCRIPTION_COMMAND) != REDIS_OK) { REDIS_LOG_ERROR(NULL, "Failed to enqueue asynchronous Sentinel subscription command (error=%d, sentinel=%s:%d): %s", isentinel->context->err, isentinel->host, isentinel->port, HIREDIS_ERRSTR(isentinel->context)); redisAsyncFree(isentinel->context); isentinel->context = NULL; } } } else { if (isentinel->context != NULL) { REDIS_LOG_ERROR(NULL, "Failed to establish Sentinel connection (error=%d, sentinel=%s:%d): %s", isentinel->context->err, isentinel->host, isentinel->port, HIREDIS_ERRSTR(isentinel->context)); redisAsyncFree(isentinel->context); isentinel->context = NULL; } else { REDIS_LOG_ERROR(NULL, "Failed to establish Sentinel connection (sentinel=%s:%d)", isentinel->host, isentinel->port); } } } } // Look for pending Pub/Sub events, handle those events, update servers // and continue execution. ev_loop(loop, EVRUN_NOWAIT); // Only update database objects if a proactive discovery has been // explicitly requested or if some change was found during this check. Lck_Lock(&state->config->mutex); if ((state->config->sentinels.discovery) || (state->last_change >= now)) { unsafe_update_dbs(state); state->config->sentinels.discovery = 0; } Lck_Unlock(&state->config->mutex); // Wait for the next check. usleep(1000000); } // Log event. Lck_Lock(&state->config->mutex); REDIS_LOG_INFO(NULL, "Sentinel thread stopped (locations=%s, period=%d)", state->config->sentinels.locations, state->config->sentinels.period); Lck_Unlock(&state->config->mutex); // Done! free_state(state); ev_loop_destroy(loop); return NULL; } /****************************************************************************** * UTILITIES. *****************************************************************************/ static struct server * new_server( struct sentinel *sentinel, const char *host, unsigned port, enum REDIS_SERVER_ROLE role, unsigned down) { struct server *result; ALLOC_OBJ(result, SERVER_MAGIC); AN(result); result->host = strdup(host); AN(result->host); result->port = port; result->role = role; result->down = down; result->sentinel = sentinel; return result; } static void free_server(struct server *server) { CHECK_OBJ_NOTNULL(server, SERVER_MAGIC); free((void *) server->host); server->host = NULL; server->port = 0; server->role = REDIS_SERVER_TBD_ROLE; server->down = 0; server->sentinel = NULL; FREE_OBJ(server); } static struct sentinel * new_sentinel(struct state *state, const char *host, unsigned host_len, unsigned port) { struct sentinel *result; ALLOC_OBJ(result, SENTINEL_MAGIC); AN(result); result->host = strndup(host, host_len); AN(result->host); result->port = port; result->context = NULL; result->state = state; return result; } static void free_sentinel(struct sentinel *sentinel) { CHECK_OBJ_NOTNULL(sentinel, SENTINEL_MAGIC); free((void *) sentinel->host); sentinel->host = NULL; sentinel->port = 0; if (sentinel->context != NULL) { redisAsyncFree(sentinel->context); sentinel->context = NULL; } sentinel->state = NULL; FREE_OBJ(sentinel); } static struct state * new_state( vcl_state_t *config, unsigned period, struct timeval connection_timeout, struct timeval command_timeout, enum REDIS_PROTOCOL protocol, #ifdef TLS_ENABLED redisSSLContext *tls_ssl_ctx, #endif const char *password) { struct state *result; ALLOC_OBJ(result, STATE_MAGIC); AN(result); result->config = config; VTAILQ_INIT(&result->sentinels); result->period = period; result->connection_timeout = connection_timeout; result->command_timeout = command_timeout; result->protocol = protocol; #ifdef TLS_ENABLED result->tls_ssl_ctx = tls_ssl_ctx; #endif if (password != NULL) { result->password = strdup(password); AN(result->password); } else { result->password = NULL; } result->last_change = 0; result->next_discovery = 0; VTAILQ_INIT(&result->servers); return result; } static void free_state(struct state *state) { CHECK_OBJ_NOTNULL(state, STATE_MAGIC); state->config = NULL; struct sentinel *isentinel; while (!VTAILQ_EMPTY(&state->sentinels)) { isentinel = VTAILQ_FIRST(&state->sentinels); CHECK_OBJ_NOTNULL(isentinel, SENTINEL_MAGIC); VTAILQ_REMOVE(&state->sentinels, isentinel, list); free_sentinel(isentinel); } state->period = 0; state->connection_timeout = (struct timeval){ 0 }; state->command_timeout = (struct timeval){ 0 }; state->protocol = REDIS_PROTOCOL_DEFAULT; #ifdef TLS_ENABLED if (state->tls_ssl_ctx != NULL) { redisFreeSSLContext(state->tls_ssl_ctx); state->tls_ssl_ctx = NULL; } #endif if (state->password != NULL) { free((void *) state->password); state->password = NULL; } state->last_change = 0; state->next_discovery = 0; struct server *iserver; while (!VTAILQ_EMPTY(&state->servers)) { iserver = VTAILQ_FIRST(&state->servers); CHECK_OBJ_NOTNULL(iserver, SERVER_MAGIC); VTAILQ_REMOVE(&state->servers, iserver, list); free_server(iserver); } FREE_OBJ(state); } static void unsafe_set_locations(struct state *state, const char *locations) { // Initializations unsigned error = 0; // Parse input. const char *p = locations; while (*p != '\0') { // Find next item. while (isspace(*p)) p++; const char *q = p; while (*q != '\0' && *q != ',') q++; if (p == q) { error = 10; break; } // Parse port. const char *r = q - 1; while (r > p && isspace(*r)) r--; while (r > p && isdigit(*r)) r--; if (*r != ':') { error = 20; break; } r++; if (!isdigit(*r)) { error = 30; break; } const char *s; int port = strtoul(r, (char **)&s, 10); if (r == s || (*s != ',' && !isspace(*s) && *s != '\0') || port < 0 || port > 65536) { error = 40; break; } // Parse host. if (r - p <= 1) { error = 50; break; } const char *host = p; unsigned host_len = r - p - 1; // Store parsed Sentinel. struct sentinel *sentinel = new_sentinel(state, host, host_len, port); VTAILQ_INSERT_TAIL(&state->sentinels, sentinel, list); // More items? p = q; while (isspace(*p) || (*p == ',')) p++; } // Check error flag. if (error) { // Release parsed Sentinels. struct sentinel *isentinel; while (!VTAILQ_EMPTY(&state->sentinels)) { isentinel = VTAILQ_FIRST(&state->sentinels); CHECK_OBJ_NOTNULL(isentinel, SENTINEL_MAGIC); VTAILQ_REMOVE(&state->sentinels, isentinel, list); free_sentinel(isentinel); } // Log error. REDIS_LOG_ERROR(NULL, "Got error while parsing Sentinels (error=%d, locations=%s)", error, locations); } } static void store_sentinel_reply( struct sentinel *sentinel, const char *host, unsigned port, enum REDIS_SERVER_ROLE role, int down) { // Initializations. struct server *server = NULL; // Search for server matching host & port. VTAILQ_FOREACH(server, &sentinel->state->servers, list) { CHECK_OBJ_NOTNULL(server, SERVER_MAGIC); if ((server->port == port) && (strcmp(server->host, host) == 0)) { break; } } // Register / update server. if (server == NULL) { server = new_server(sentinel, host, port, role, down > 0); VTAILQ_INSERT_TAIL(&sentinel->state->servers, server, list); sentinel->state->last_change = time(NULL); } else if ((server->role != role) || ((down >= 0) && (server->down != down))) { server->sentinel = sentinel; server->role = role; if (down >= 0) { server->down = down; } sentinel->state->last_change = time(NULL); } } static void parse_sentinel_notification(struct sentinel *sentinel, redisReply *reply) { // Check reply format. if ((reply != NULL) && ((reply->type == REDIS_REPLY_ARRAY || RESP3_SWITCH(reply->type == REDIS_REPLY_PUSH, 0))) && (reply->elements == 4) && (reply->element[0]->type == REDIS_REPLY_STRING) && (strcmp(reply->element[0]->str, "pmessage") == 0) && (reply->element[2]->type == REDIS_REPLY_STRING) && (reply->element[3]->type == REDIS_REPLY_STRING)) { // Initializations. char *ctx, *ptr; const char *event = reply->element[2]->str; char *payload = strdup(reply->element[3]->str); AN(payload); // +sdown ... // -sdown ... // +odown ... // -odown ... if ((strcmp(event, "+sdown") == 0) || (strcmp(event, "-sdown") == 0) || (strcmp(event, "+odown") == 0) || (strcmp(event, "-odown") == 0)) { // Extract . enum REDIS_SERVER_ROLE role; ptr = strtok_r(payload, " ", &ctx); if (ptr != NULL) { if (strcmp(ptr, "master") == 0) { role = REDIS_SERVER_MASTER_ROLE; } else if (strcmp(ptr, "slave") == 0) { role = REDIS_SERVER_SLAVE_ROLE; } else { goto stop; } } else { goto stop; } // Extract . ptr = strtok_r(NULL, " ", &ctx); if (ptr == NULL) { goto stop; } // Extract . ptr = strtok_r(NULL, " ", &ctx); const char *ip; if (ptr != NULL) { ip = ptr; } else { goto stop; } // Extract . ptr = strtok_r(NULL, " ", &ctx); unsigned port; if (ptr != NULL) { port = atoi(ptr); } else { goto stop; } // Register / update server. store_sentinel_reply(sentinel, ip, port, role, event[0] == '+'); // +switch-master ... } else if (strcmp(event, "+switch-master") == 0) { // Extract . ptr = strtok_r(payload, " ", &ctx); if (ptr == NULL) { goto stop; } // Extract . ptr = strtok_r(NULL, " ", &ctx); const char *old_ip; if (ptr != NULL) { old_ip = ptr; } else { goto stop; } // Extract . ptr = strtok_r(NULL, " ", &ctx); unsigned old_port; if (ptr != NULL) { old_port = atoi(ptr); } else { goto stop; } // Extract . ptr = strtok_r(NULL, " ", &ctx); const char *new_ip; if (ptr != NULL) { new_ip = ptr; } else { goto stop; } // Extract . ptr = strtok_r(NULL, " ", &ctx); unsigned new_port; if (ptr != NULL) { new_port = atoi(ptr); } else { goto stop; } // Register / update server. store_sentinel_reply( sentinel, old_ip, old_port, REDIS_SERVER_SLAVE_ROLE, -1); store_sentinel_reply( sentinel, new_ip, new_port, REDIS_SERVER_MASTER_ROLE, 0); } stop: // Release payload. free(payload); } } static void parse_sentinel_discovery( struct state *state, struct sentinel *sentinel, redisReply *reply, const char ***master_names) { // Initializations. if (master_names != NULL) { *master_names = NULL; } // Check reply format. if (reply->type == REDIS_REPLY_ARRAY) { // Initializations. unsigned imaster_names = 0; if (master_names != NULL) { *master_names = malloc((reply->elements + 1) * sizeof(const char *)); AN(*master_names); (*master_names)[0] = NULL; } // Check reply contents. const char *name, *value; for (int i = 0; i < reply->elements; i++) { if (reply->element[i]->type == REDIS_REPLY_ARRAY || RESP3_SWITCH(reply->element[i]->type == REDIS_REPLY_MAP, 0)) { // Initializations. const char *master_name = NULL; const char *host = NULL; unsigned port = 0; enum REDIS_SERVER_ROLE role = REDIS_SERVER_TBD_ROLE; unsigned down = 0; // Look for relevant properties. for (int j = 0; j + 1 < reply->element[i]->elements; j += 2) { if ((reply->element[i]->element[j]->type == REDIS_REPLY_STRING) && (reply->element[i]->element[j+1]->type == REDIS_REPLY_STRING)) { name = reply->element[i]->element[j]->str; value = reply->element[i]->element[j+1]->str; if (strcmp(name, "name") == 0) { master_name = value; } else if (strcmp(name, "ip") == 0) { host = value; } else if (strcmp(name, "port") == 0) { port = atoi(value); } else if (strcmp(name, "flags") == 0) { if (strstr(value, "master") != NULL) { role = REDIS_SERVER_MASTER_ROLE; } if (strstr(value, "slave") != NULL) { role = REDIS_SERVER_SLAVE_ROLE; } if ((strstr(value, "s_down") != NULL) || (strstr(value, "o_down") != NULL)) { down = 1; } } } } // Insert in the list of discovered master names? if ((master_name != NULL) && (master_names != NULL)) { (*master_names)[imaster_names++] = master_name; (*master_names)[imaster_names] = NULL; } // Register / update server if all required properties have // been found. if ((host != NULL) && (port > 0) && (role != REDIS_SERVER_TBD_ROLE)) { store_sentinel_reply(sentinel, host, port, role, down); } } } } else { REDIS_LOG_ERROR(NULL, "Unexpected Sentinel discovery command reply (type=%d, sentinel=%s:%d)", reply->type, sentinel->host, sentinel->port); } } static void discover_servers(struct state *state) { // Query all registered Sentinels. struct sentinel *isentinel; VTAILQ_FOREACH(isentinel, &state->sentinels, list) { // Assertions. CHECK_OBJ_NOTNULL(isentinel, SENTINEL_MAGIC); // Create context. redisContext *rcontext; if ((state->connection_timeout.tv_sec > 0) || (state->connection_timeout.tv_usec > 0)) { rcontext = redisConnectWithTimeout( isentinel->host, isentinel->port, state->connection_timeout); } else { rcontext = redisConnect( isentinel->host, isentinel->port); } if (rcontext == NULL) { REDIS_LOG_ERROR(NULL, "Failed to establish Sentinel connection (sentinel=%s:%d)", isentinel->host, isentinel->port); } else if (rcontext->err) { REDIS_LOG_ERROR(NULL, "Failed to establish Sentinel connection (error=%d, sentinel=%s:%d): %s", rcontext->err, isentinel->host, isentinel->port, HIREDIS_ERRSTR(rcontext)); redisFree(rcontext); rcontext = NULL; } #ifdef TLS_ENABLED // Setup TLS. if ((rcontext != NULL) && (state->tls_ssl_ctx != NULL) && (redisInitiateSSLWithContext(rcontext, state->tls_ssl_ctx) != REDIS_OK)) { REDIS_LOG_ERROR(NULL, "Failed to secure Sentinel connection (error=%d, sentinel=%s:%d): %s", rcontext->err, isentinel->host, isentinel->port, HIREDIS_ERRSTR(rcontext)); redisFree(rcontext); rcontext = NULL; } #endif // Send 'AUTH' command. if ((rcontext != NULL) && (state->password != NULL)) { redisReply *reply = redisCommand(rcontext, "AUTH %s", state->password); if ((rcontext->err) || (reply == NULL) || (reply->type != REDIS_REPLY_STATUS) || (strcmp(reply->str, "OK") != 0)) { REDIS_LOG_ERROR(NULL, "Failed to execute Sentinel AUTH command (error=%d, sentinel=%s:%d): %s", rcontext->err, isentinel->host, isentinel->port, HIREDIS_ERRSTR(rcontext, reply)); redisFree(rcontext); rcontext = NULL; } } // Send 'HELLO' command. if ((rcontext != NULL) && (state->protocol != REDIS_PROTOCOL_DEFAULT)) { redisReply *reply = redisCommand(rcontext, "HELLO %d", state->protocol); if ((rcontext->err) || (reply == NULL) || (reply->type != REDIS_REPLY_ARRAY && RESP3_SWITCH(reply->type != REDIS_REPLY_MAP, 1)) ) { REDIS_LOG_ERROR(NULL, "Failed to execute Sentinel HELLO command (error=%d, sentinel=%s:%d): %s", rcontext->err, isentinel->host, isentinel->port, HIREDIS_ERRSTR(rcontext, reply)); redisFree(rcontext); rcontext = NULL; } } // Check context. if (rcontext != NULL) { // Set command execution timeout. int tr = redisSetTimeout(rcontext, state->command_timeout); if (tr != REDIS_OK) { REDIS_LOG_ERROR(NULL, "Failed to set Sentinel command execution timeout (error=%d, sentinel=%s:%d)", tr, isentinel->host, isentinel->port); } // Send 'SENTINEL masters' command in order to get a list of // monitored masters and their state. const char **master_names = NULL; redisReply *reply1 = redisCommand(rcontext, "SENTINEL masters"); if (reply1 != NULL) { parse_sentinel_discovery(state, isentinel, reply1, &master_names); // Send 'SENTINEL slaves ' command for each // discovered master name in order to get the list of // monitored slaves and their state. if (master_names != NULL) { for (int i = 0; master_names[i] != NULL ; i++) { if (!rcontext->err) { redisReply *reply2 = redisCommand(rcontext, "SENTINEL slaves %s", master_names[i]); if (reply2 != NULL) { parse_sentinel_discovery(state, isentinel, reply2, NULL); freeReplyObject(reply2); } else { REDIS_LOG_ERROR(NULL, "Failed to execute Sentinel slaves command (error=%s, master_name=%s, sentinel=%s:%d): %s", rcontext->err, master_names[i], isentinel->host, isentinel->port, HIREDIS_ERRSTR(rcontext)); } } else { REDIS_LOG_ERROR(NULL, "Failed to reuse Sentinel connection (error=%d, sentinel=%s:%d): %s", rcontext->err, isentinel->host, isentinel->port, HIREDIS_ERRSTR(rcontext)); break; } } free(master_names); } freeReplyObject(reply1); } else { REDIS_LOG_ERROR(NULL, "Failed to execute Sentinel masters command (error=%d, sentinel=%s:%d): %s", rcontext->err, isentinel->host, isentinel->port, HIREDIS_ERRSTR(rcontext)); } // Release context. redisFree(rcontext); } } } static void unsafe_update_dbs_aux(struct state *state, redis_server_t *server) { // Assertions. Lck_AssertHeld(&state->config->mutex); Lck_AssertHeld(&server->db->mutex); // Look for a discovered server matching this one. struct server *is; VTAILQ_FOREACH(is, &state->servers, list) { CHECK_OBJ_NOTNULL(is, SERVER_MAGIC); if ((server->location.parsed.address.port == is->port) && (strcmp(server->location.parsed.address.host, is->host) == 0)) { // Change role? if (server->role != is->role) { VTAILQ_REMOVE( &server->db->servers[server->weight][server->role], server, list); server->role = is->role; VTAILQ_INSERT_TAIL( &server->db->servers[server->weight][server->role], server, list); REDIS_LOG_INFO(NULL, "Server role updated (db=%s, server=%s, sentinel=%s:%d, role=%d)", server->db->name, server->location.raw, is->sentinel->host, is->sentinel->port, is->role); } // Change sickness flag? unsigned now = time(NULL); if (server->sickness.exp <= now) { if (is->down) { server->sickness.exp = UINT_MAX; REDIS_LOG_INFO(NULL, "Server sickness tag set (db=%s, server=%s, sentinel=%s:%d)", server->db->name, server->location.raw, is->sentinel->host, is->sentinel->port); } } else { if (!is->down) { server->sickness.exp = now; REDIS_LOG_INFO(NULL, "Server sickness tag cleared (db=%s, server=%s, sentinel=%s:%d)", server->db->name, server->location.raw, is->sentinel->host, is->sentinel->port); } } // Found! break; } } } static void unsafe_update_dbs(struct state *state) { // Assertions. Lck_AssertHeld(&state->config->mutex); // Look for servers matching servers previously discovered by Sentinel. database_t *idb; VTAILQ_FOREACH(idb, &state->config->dbs, list) { CHECK_OBJ_NOTNULL(idb, DATABASE_MAGIC); if (!idb->db->cluster.enabled) { Lck_Lock(&idb->db->mutex); for (unsigned iweight = 0; iweight < NREDIS_SERVER_WEIGHTS; iweight++) { for (enum REDIS_SERVER_ROLE irole = 0; irole < NREDIS_SERVER_ROLES; irole++) { redis_server_t *iserver, *iserver_tmp; VTAILQ_FOREACH_SAFE(iserver, &(idb->db->servers[iweight][irole]), list, iserver_tmp) { CHECK_OBJ_NOTNULL(iserver, REDIS_SERVER_MAGIC); if (iserver->location.type == REDIS_SERVER_LOCATION_HOST_TYPE) { unsafe_update_dbs_aux(state, iserver); } } } } Lck_Unlock(&idb->db->mutex); } } } libvmod-redis-21.0/src/sentinel.h000066400000000000000000000003541476735432100167730ustar00rootroot00000000000000#ifndef SENTINEL_H_INCLUDED #define SENTINEL_H_INCLUDED #include "core.h" void unsafe_sentinel_start(vcl_state_t *config); void unsafe_sentinel_discovery(vcl_state_t *config); void unsafe_sentinel_stop(vcl_state_t *config); #endif libvmod-redis-21.0/src/sha1.c000066400000000000000000000167601476735432100160110ustar00rootroot00000000000000#include "config.h" /* SHA-1 in C By Steve Reid 100% Public Domain Test Vectors (from FIPS PUB 180-1) "abc" A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 A million repetitions of "a" 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F */ /* #define LITTLE_ENDIAN * This should be #define'd already, if true. */ /* #define SHA1HANDSOFF * Copies data before messing with it. */ #define SHA1HANDSOFF #include #include /* for uint32_t */ #include #include "sha1.h" #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) /* blk0() and blk() perform the initial expand. */ /* I got the idea of expanding during the round function from SSLeay */ #if BYTE_ORDER == LITTLE_ENDIAN #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ |(rol(block->l[i],8)&0x00FF00FF)) #elif BYTE_ORDER == BIG_ENDIAN #define blk0(i) block->l[i] #else #error "Endianness not defined!" #endif #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ ^block->l[(i+2)&15]^block->l[i&15],1)) /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); /* Hash a single 512-bit block. This is the core of the algorithm. */ void SHA1Transform( uint32_t state[5], const unsigned char buffer[64] ) { uint32_t a, b, c, d, e; typedef union { unsigned char c[64]; uint32_t l[16]; } CHAR64LONG16; #ifdef SHA1HANDSOFF CHAR64LONG16 block[1]; /* use array to appear as a pointer */ memcpy(block, buffer, 64); #else /* The following had better never be used because it causes the * pointer-to-const buffer to be cast into a pointer to non-const. * And the result is written through. I threw a "const" in, hoping * this will cause a diagnostic. */ CHAR64LONG16 *block = (const CHAR64LONG16 *) buffer; #endif /* Copy context->state[] to working vars */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; /* 4 rounds of 20 operations each. Loop unrolled. */ R0(a, b, c, d, e, 0); R0(e, a, b, c, d, 1); R0(d, e, a, b, c, 2); R0(c, d, e, a, b, 3); R0(b, c, d, e, a, 4); R0(a, b, c, d, e, 5); R0(e, a, b, c, d, 6); R0(d, e, a, b, c, 7); R0(c, d, e, a, b, 8); R0(b, c, d, e, a, 9); R0(a, b, c, d, e, 10); R0(e, a, b, c, d, 11); R0(d, e, a, b, c, 12); R0(c, d, e, a, b, 13); R0(b, c, d, e, a, 14); R0(a, b, c, d, e, 15); R1(e, a, b, c, d, 16); R1(d, e, a, b, c, 17); R1(c, d, e, a, b, 18); R1(b, c, d, e, a, 19); R2(a, b, c, d, e, 20); R2(e, a, b, c, d, 21); R2(d, e, a, b, c, 22); R2(c, d, e, a, b, 23); R2(b, c, d, e, a, 24); R2(a, b, c, d, e, 25); R2(e, a, b, c, d, 26); R2(d, e, a, b, c, 27); R2(c, d, e, a, b, 28); R2(b, c, d, e, a, 29); R2(a, b, c, d, e, 30); R2(e, a, b, c, d, 31); R2(d, e, a, b, c, 32); R2(c, d, e, a, b, 33); R2(b, c, d, e, a, 34); R2(a, b, c, d, e, 35); R2(e, a, b, c, d, 36); R2(d, e, a, b, c, 37); R2(c, d, e, a, b, 38); R2(b, c, d, e, a, 39); R3(a, b, c, d, e, 40); R3(e, a, b, c, d, 41); R3(d, e, a, b, c, 42); R3(c, d, e, a, b, 43); R3(b, c, d, e, a, 44); R3(a, b, c, d, e, 45); R3(e, a, b, c, d, 46); R3(d, e, a, b, c, 47); R3(c, d, e, a, b, 48); R3(b, c, d, e, a, 49); R3(a, b, c, d, e, 50); R3(e, a, b, c, d, 51); R3(d, e, a, b, c, 52); R3(c, d, e, a, b, 53); R3(b, c, d, e, a, 54); R3(a, b, c, d, e, 55); R3(e, a, b, c, d, 56); R3(d, e, a, b, c, 57); R3(c, d, e, a, b, 58); R3(b, c, d, e, a, 59); R4(a, b, c, d, e, 60); R4(e, a, b, c, d, 61); R4(d, e, a, b, c, 62); R4(c, d, e, a, b, 63); R4(b, c, d, e, a, 64); R4(a, b, c, d, e, 65); R4(e, a, b, c, d, 66); R4(d, e, a, b, c, 67); R4(c, d, e, a, b, 68); R4(b, c, d, e, a, 69); R4(a, b, c, d, e, 70); R4(e, a, b, c, d, 71); R4(d, e, a, b, c, 72); R4(c, d, e, a, b, 73); R4(b, c, d, e, a, 74); R4(a, b, c, d, e, 75); R4(e, a, b, c, d, 76); R4(d, e, a, b, c, 77); R4(c, d, e, a, b, 78); R4(b, c, d, e, a, 79); /* Add the working vars back into context.state[] */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; /* Wipe variables */ a = b = c = d = e = 0; #ifdef SHA1HANDSOFF memset(block, '\0', sizeof(block)); #endif } /* SHA1Init - Initialize new context */ void SHA1Init( SHA1_CTX * context ) { /* SHA1 initialization constants */ context->state[0] = 0x67452301; context->state[1] = 0xEFCDAB89; context->state[2] = 0x98BADCFE; context->state[3] = 0x10325476; context->state[4] = 0xC3D2E1F0; context->count[0] = context->count[1] = 0; } /* Run your data through this. */ void SHA1Update( SHA1_CTX * context, const unsigned char *data, uint32_t len ) { uint32_t i; uint32_t j; j = context->count[0]; if ((context->count[0] += len << 3) < j) context->count[1]++; context->count[1] += (len >> 29); j = (j >> 3) & 63; if ((j + len) > 63) { memcpy(&context->buffer[j], data, (i = 64 - j)); SHA1Transform(context->state, context->buffer); for (; i + 63 < len; i += 64) { SHA1Transform(context->state, &data[i]); } j = 0; } else i = 0; memcpy(&context->buffer[j], &data[i], len - i); } /* Add padding and return the message digest. */ void SHA1Final( unsigned char digest[20], SHA1_CTX * context ) { unsigned i; unsigned char finalcount[8]; unsigned char c; #if 0 /* untested "improvement" by DHR */ /* Convert context->count to a sequence of bytes * in finalcount. Second element first, but * big-endian order within element. * But we do it all backwards. */ unsigned char *fcp = &finalcount[8]; for (i = 0; i < 2; i++) { uint32_t t = context->count[i]; int j; for (j = 0; j < 4; t >>= 8, j++) *--fcp = (unsigned char) t} #else for (i = 0; i < 8; i++) { finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ } #endif c = 0200; SHA1Update(context, &c, 1); while ((context->count[0] & 504) != 448) { c = 0000; SHA1Update(context, &c, 1); } SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ for (i = 0; i < 20; i++) { digest[i] = (unsigned char) ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); } /* Wipe variables */ memset(context, '\0', sizeof(*context)); memset(&finalcount, '\0', sizeof(finalcount)); } void SHA1( char *hash_out, const char *str, int len) { SHA1_CTX ctx; unsigned int ii; SHA1Init(&ctx); for (ii=0; ii 100% Public Domain */ #include "stdint.h" typedef struct { uint32_t state[5]; uint32_t count[2]; unsigned char buffer[64]; } SHA1_CTX; void SHA1Transform( uint32_t state[5], const unsigned char buffer[64] ); void SHA1Init( SHA1_CTX * context ); void SHA1Update( SHA1_CTX * context, const unsigned char *data, uint32_t len ); void SHA1Final( unsigned char digest[20], SHA1_CTX * context ); void SHA1( char *hash_out, const char *str, int len); #endif /* SHA1_H_INCLUDED */ libvmod-redis-21.0/src/tests/000077500000000000000000000000001476735432100161415ustar00rootroot00000000000000libvmod-redis-21.0/src/tests/assets/000077500000000000000000000000001476735432100174435ustar00rootroot00000000000000libvmod-redis-21.0/src/tests/assets/hashslot-keys.txt000066400000000000000000007522321476735432100230150ustar00rootroot000000000000000: sbdsvkwr 1: elrhmonw 2: yxjsrnkd 3: rouivmie 4: vryfpehm 5: cvajwnnv 6: yhmhkblx 7: bkwqbend 8: iqyubjmw 9: atisufht 10: qtirxujd 11: kjnoincf 12: kheepsfx 13: yedqviwe 14: iclhpqvx 15: txiencwh 16: dqbybvme 17: ykrpwhlh 18: ifcsblhe 19: hhdnwcfb 20: tamqkrmv 21: otyynpet 22: errvfdps 23: ffeigedn 24: epukswnr 25: pfmoggtk 26: mrdtqvyr 27: rngrqylf 28: rerhfchr 29: vwrijpkd 30: hwntnwcm 31: cdlkkjie 32: amrdvoyl 33: isltggiy 34: ohehjxch 35: vyuqmgrp 36: borflnpx 37: hwskcyoy 38: sulpqwqr 39: kuydjthf 40: toqkrfan 41: lxphsalu 42: qdnupmhi 43: xnxamimb 44: bbyvixnx 45: rasjvole 46: fpmpeypq 47: sjeetycs 48: gxpnunrr 49: jvcijgaw 50: iicyvcxw 51: faerqnqb 52: tdxkgkcn 53: xjtxtrvu 54: rwcdibys 55: vguwmycr 56: lwuopyis 57: rsyvkhdb 58: uuvowkem 59: pfsfkjav 60: ytormfom 61: dlnpyrar 62: eprfodbe 63: niefyxlj 64: spqnhnaw 65: cmrlfehb 66: brnbuthg 67: hweijagd 68: suwllijl 69: mcmdfnit 70: waxpoeqy 71: lvbiqoyh 72: iiqkmryk 73: dndywnxi 74: drcppiff 75: nclxwulk 76: xxoqijsx 77: wdodqhjh 78: qbmoevpw 79: grbiaise 80: yvtnvswd 81: voxwfmil 82: cigwpdqs 83: dwdrdnyp 84: wmwppnhp 85: jmuyxpdq 86: qfymttwj 87: mkfrxeyh 88: tknffgxh 89: ydpvjnhi 90: cgvstxwe 91: osogflht 92: eijhtxav 93: ysfbjbxx 94: xvyrwqrj 95: hjijcjov 96: hifkhfto 97: sbtnxiwl 98: vlyhyauh 99: tgtejhwp 100: whyicskx 101: hisqagqi 102: hbgbxxwl 103: ldhgixjm 104: uxlalttr 105: hvocqiuk 106: yaxqxigj 107: gjwwjnwk 108: gymieayp 109: gdyhhsch 110: qhlctmnn 111: sjqtqplw 112: mclenjkq 113: xintvofw 114: rxqkloyw 115: dxlrufhj 116: qtdolbaf 117: wmlkghqs 118: tfahgcqk 119: grifqigw 120: pssjslfq 121: ugonnfim 122: svfwfthj 123: rtjtayfx 124: xyhxmidq 125: ifnvrhpc 126: squvwgws 127: ugqlnhds 128: ynljjoqr 129: gseavydk 130: eywmeflo 131: nxpairga 132: sxwtgamy 133: blxjvvtx 134: poxdomqt 135: uakedfvn 136: ueqhuvif 137: eglmdynt 138: fwrsacru 139: dxtnywwi 140: cgwaprao 141: vxvoeylp 142: giaqaect 143: qadpealx 144: gpfyytil 145: qjavybjo 146: oxptlgdk 147: shypncmf 148: nqfrpvxj 149: axdptpkv 150: naatambn 151: mrujeboh 152: pmfgognp 153: dcuowhrc 154: ofjoucyl 155: ouufeiud 156: shjotfwj 157: xjlhefwa 158: gxndhcim 159: fmqjiwgu 160: ihdeuaqp 161: pknuupym 162: rgrrfnvv 163: uuijyyun 164: giymddms 165: ffgpejvs 166: jfcuawlk 167: biknuvpf 168: sgpnwdpk 169: qbfsmjuw 170: fbflgtcf 171: vqwymdri 172: cjnkcsio 173: owpghlmm 174: jlgfwkok 175: wyrhyasn 176: jiabsnul 177: mprrnond 178: wqgvneqa 179: fphathre 180: wbjjsnkd 181: rhfpdrqs 182: mqnyonmm 183: fbmioaxv 184: gjslvrso 185: baywrhmv 186: cbjpimsa 187: onjmfyii 188: ewaqgpot 189: hacmvvvg 190: xeuwhady 191: evogcdsg 192: bctgatfv 193: kyjgoxfw 194: tcehqsav 195: cernlkuk 196: vuhnqtku 197: qseepsya 198: aklxratt 199: diovudkp 200: myvrjsos 201: yxjcnsdl 202: ncobfbab 203: bkiyakih 204: xqjpgnfx 205: aohardjr 206: ickatxuv 207: ngurjtcn 208: apqnrymf 209: vbqfwpin 210: lnkmrxpy 211: tsvnjqst 212: gvctvjlo 213: hdyajkqt 214: hcyarfru 215: qxaivcvs 216: yhekryem 217: dnqfittm 218: xnvhrfun 219: vawaxhcu 220: kwhssdku 221: hwbfspfq 222: wtkacsiy 223: jsoaqfng 224: psptfhmb 225: vyyjectq 226: ubwvhdwe 227: gglsqnbv 228: ppjmaapv 229: kfreliyg 230: evhyprbv 231: jyoecoav 232: okwvnygr 233: ekbgjyct 234: hxdvojvp 235: gmnobiry 236: svvnsujn 237: jeubhxcp 238: yoegqomb 239: hkliamef 240: anipnukr 241: djkifwim 242: pynepiwd 243: tninxyyf 244: qsiixuuw 245: uesiokyg 246: pipjdlhn 247: cynhmnhf 248: mhffexjj 249: gwrywoea 250: nwqmbjve 251: yamoiibj 252: rtjigaas 253: xeqltxgk 254: ssekfxcc 255: wjpfqlyw 256: efpblthv 257: xaggwpps 258: aqpvekio 259: stnfkqho 260: gvpicoyo 261: ugiwipgv 262: sookpxvp 263: ugffjhoj 264: qgrsqfgq 265: dxvtdklt 266: maqjnunq 267: fquaygjw 268: nxjoifbw 269: ysbeftmk 270: xfvsvbau 271: qendorea 272: rmvptowg 273: dopkqdku 274: xdeudevp 275: tgdglvvl 276: jatflolu 277: likdmjpm 278: wkqumqvo 279: enjvinnw 280: tmxlpuvu 281: kaiusoaq 282: bnujtyow 283: aayuollr 284: ddsqipgh 285: nrltqopi 286: ctalpohp 287: wcwdnfbx 288: fmldvbry 289: ukgdqssq 290: mcydjciu 291: jagryfru 292: ixymklhc 293: bwddurxr 294: boqjlebq 295: bbdqxrgk 296: bnilvwfv 297: ujaavgug 298: bahtktxf 299: owvvgmsc 300: khfocqkq 301: apmnbqlk 302: kkerbnmq 303: kjexbpno 304: safqgmok 305: uoksllof 306: vkqbjakv 307: wweytxuf 308: wuwcxdsd 309: pyyyiacp 310: mxdojedq 311: lrbsatqw 312: cycxmsnd 313: gpcjesqr 314: cqctvbfb 315: xibscfkd 316: iayqhnjc 317: kfdmhqdk 318: prsrhqnc 319: pmmyqapg 320: pbpopmso 321: nspetoye 322: axnwehwx 323: yujijres 324: gpqhjmgq 325: usseriha 326: apogoeoj 327: ttatcsas 328: tusmetsf 329: nygqdhvr 330: qbnujaks 331: ckbvwedc 332: denohvfi 333: axiqinpv 334: xhwylonp 335: yffmwmtr 336: jnmdqwpa 337: ucwryxat 338: osbmmspf 339: salmwkar 340: tliyfnmt 341: sugtpysr 342: mymfqpvt 343: menjkpfq 344: abricjti 345: nljtxbfl 346: hprmoqlf 347: evnaossg 348: irfnvlha 349: yneysfcu 350: fickwrpo 351: dlyufiuo 352: komylcss 353: mgmiqlju 354: lqfyklhl 355: bfgsxdpm 356: hnoxigce 357: kkwmnjmn 358: hhejwcmk 359: pukqdyrg 360: ysnjlpew 361: bdgbhosj 362: vvbtsegy 363: grxfijor 364: bmxdrijf 365: kcnhorgg 366: lueddnyj 367: epxhgqnc 368: vgdxpgme 369: nplaqfwm 370: odxkgnra 371: xcwovnbm 372: ehdeouej 373: suftiiff 374: bxcoiqwl 375: achyhfrc 376: enhviasg 377: ltrgfxpy 378: unlxmslg 379: btolynis 380: qkqhowqp 381: jfkiwqve 382: pebmxrpq 383: mhvgwhig 384: onhstgst 385: fufekyuy 386: pvrkejpv 387: ffpcjvqb 388: vexphhmm 389: fsdytisd 390: qkgwytaq 391: qbnaxpau 392: okhqkuxi 393: xsrchysj 394: bhjebluh 395: yqbasmli 396: ytpgothk 397: pwlcwruk 398: knihwkxu 399: rhhwjxpt 400: fwitwrqb 401: hdujywqu 402: lvlidtts 403: yrvuvjbq 404: gsxdwxgx 405: yqsvprkd 406: ouwocdyq 407: flylugbx 408: kvgxfyhn 409: ggyulvyg 410: xxyhcreq 411: ldrhpklk 412: pbcugrch 413: hyxfdtol 414: erkuhlrv 415: juwjfvns 416: fcsaaafm 417: cwitxcww 418: alvwbllf 419: ohrtaecq 420: caaebckw 421: kdfoxjwf 422: vtllqqth 423: dfjmiheg 424: anxnoixk 425: xarxlvup 426: agxhlrre 427: ooxdqwyy 428: pgctypqb 429: vsaiufsf 430: crhjwojl 431: byqewxpe 432: aidoqqfb 433: kkuhvowa 434: gqyfpngp 435: fsmqgnvc 436: sxhpbhqc 437: bjgvtqst 438: hyrbjhwa 439: qepgljwc 440: njbhqnkp 441: mrxnxhal 442: pwavllhg 443: iyfepiqu 444: fqpnnuka 445: fmphoqtl 446: rrakbpdv 447: jsqditgh 448: egosrwpm 449: qfglrjre 450: vwwxmodq 451: lbsbuuqq 452: apvmpmag 453: dlijjwat 454: qdsrsvqr 455: pxulompu 456: obmnhkas 457: kljmexix 458: cyomfnod 459: yqxnuvve 460: fcwyaxsc 461: mcplrkld 462: yglrkowu 463: wvexggpw 464: nqmtelmo 465: vjuaxjhk 466: fwbawvit 467: srmrigbf 468: bqbkodne 469: uudqrajn 470: eavvulqa 471: othrqyjj 472: dwsxfnpa 473: iundkhmy 474: chppkfra 475: qsmypgmy 476: arunvpcg 477: nopmupbk 478: cymqmokj 479: cjlbrnsx 480: eayjqmrv 481: oegdugky 482: wsiobqtr 483: avqhdymk 484: bmsogfwo 485: pbqnlahf 486: nbamaqci 487: whntkksd 488: ptesuuqh 489: gcisoiim 490: awvmpjjg 491: lkisjliy 492: cklgrlob 493: gssxshec 494: uiihdyeb 495: frqetvbk 496: bvcnhrjy 497: cpapqnli 498: cegqerxe 499: oqjmdyfe 500: weymftmw 501: gcrdyqlq 502: fgyfkctp 503: sswjryhc 504: dstevnbq 505: swsjauhq 506: iwsqrqnc 507: tgdgvcna 508: ptwdsmkt 509: qucagxbi 510: vmbajbdf 511: shtuoyfs 512: yeimthoy 513: aaxdwkrj 514: mevmaasi 515: hbrkyygg 516: oooedydo 517: rqgpeacc 518: xdkhsmto 519: thhitkxc 520: aajpatgp 521: yasynkhf 522: eeuohsdh 523: qmntbwvd 524: msiuvfmo 525: quvehhad 526: bsrfmymk 527: owgkxhhr 528: rxmnpfqi 529: syssvaag 530: sapjqjrh 531: mouemfah 532: trglwbtp 533: veydinxs 534: liywtfrp 535: wxavbqrk 536: udxdxkij 537: mmdltvtl 538: rtubakqg 539: jtkvpnqq 540: ujrlloqe 541: jfbwrkpu 542: albpbpgr 543: gvhnxpaw 544: gvnxubpq 545: ugmhhrmn 546: ihkoplun 547: ueqcgkpd 548: ouhilkqw 549: wcnxalgn 550: omtqtbpw 551: wbgmeidq 552: hkfqbwpl 553: ijuyldnc 554: dmuouuvf 555: vegrncfu 556: earoctky 557: mctkkonc 558: npincjet 559: qrxsunna 560: ahdnycpg 561: blxyfwyn 562: ynkuioal 563: lvamsmel 564: avfweubp 565: mwiriavu 566: chshoukr 567: ckcibvry 568: xheuogib 569: fovklpnl 570: jyutuwbh 571: swsqserc 572: fhrhsone 573: qlmypypa 574: pxfdidju 575: accnhneb 576: ytyuqbfm 577: nnrqecvd 578: meawgryx 579: ovrtrrlt 580: igdernrr 581: iqlwfqnm 582: lwthpfmn 583: kcxuypwe 584: grbuiuww 585: vhqdqnnv 586: ydicgkuh 587: gjqepebh 588: bxiveuat 589: wvwyehxp 590: kwcnqldr 591: akpjylaj 592: pmhstoqs 593: ftmgwrbh 594: lavuqfhe 595: sspwfolv 596: lhwttdeg 597: dgpxthum 598: fappabpw 599: cpmhqewc 600: rtcknoml 601: oirhvvpc 602: dfdtpuyc 603: wbpgmnhx 604: tbukvmbb 605: tqguljca 606: ytccjcub 607: sdpuritk 608: iiyefhan 609: bekmpjbo 610: ghyrtnnc 611: bavsiivi 612: kjqcvqnb 613: bpjsojiw 614: ghqgbwxp 615: crgasidg 616: klmeqtrj 617: iyahvkpt 618: opnlhypj 619: itlsqjxo 620: bseftytv 621: deeemvpu 622: ckulgbpv 623: jgvytdoo 624: qfmwmehr 625: wawbohsf 626: ifkqnfif 627: vrrryynv 628: fxqdswxj 629: njipsgwn 630: afmdqbeq 631: foyfrkka 632: ioswgphf 633: ofuudrdr 634: wpwmmosw 635: xwqililo 636: ccnvyveb 637: tbvkxrld 638: ibdtfvvt 639: mxigsgrs 640: ygkctktj 641: ivvktqeo 642: qthhxppq 643: hpjrniug 644: lhkecwny 645: imeeeqst 646: rtgyflts 647: vtqcwulu 648: gccnxecn 649: suoaswjw 650: yllopwfg 651: qkrehwef 652: mgcnpunl 653: flyglihf 654: hfwmpyle 655: extevydn 656: xqawjjyy 657: yydbsuev 658: lmwkccis 659: uincsrop 660: rqjfemlp 661: njvdwowe 662: tmstcutw 663: bmqewqhk 664: woiwuxxy 665: hlmdlxql 666: mjbjcfdt 667: brxcvwmr 668: ivfvvphs 669: khbvbmsj 670: pujhmlmp 671: xscewtvq 672: tonotjms 673: itoyvsje 674: ufpftxsk 675: xdhaaghf 676: fsoxerqt 677: ckbqdjbt 678: utalxnsl 679: vndaajer 680: wwerligd 681: xkwywdte 682: xsbuumhx 683: fmvtanqv 684: guahmwjh 685: iplyjhcq 686: xgglnsus 687: lwvkgbln 688: ybmcqhuy 689: hcgdmxhq 690: tpajsuau 691: noqllduc 692: ipgcgmci 693: iledvhyv 694: rpkmmtdt 695: disxccyp 696: dwgnxtfp 697: ekxruqfr 698: hqjhyqbg 699: yyxkvnvp 700: nobiorpt 701: vnnmxlfc 702: ossoxivk 703: qxjrthed 704: hbgwawwf 705: xohkbvvw 706: vriwygqy 707: wwprixir 708: cvxpcyms 709: xybitter 710: trirpjkr 711: ymdqvejl 712: nddbavsx 713: dpsbpynp 714: oamvitrc 715: nxmpmiwt 716: yujiknti 717: ujryopad 718: fwugejrm 719: tvebmjao 720: qphhhcpq 721: wprbtiwp 722: eeasooyd 723: bibvxxki 724: yimswqfb 725: qqatvfkc 726: ajnjjnej 727: ogdnxqkf 728: cppqvjtb 729: kqyfugwj 730: uvcuwvtn 731: hansgddp 732: nsmdfdaj 733: kswcujvx 734: jkxgamqk 735: mhydwcan 736: ffkkiddr 737: nykfrflp 738: neeacdcy 739: mwgeaqeo 740: vdhandfa 741: qxrlmwrl 742: hujlwmwe 743: fdsdswrb 744: ekaveoqc 745: qvxgsfqh 746: oetjkcai 747: dednahje 748: qxdvfnow 749: xpkoavwc 750: nlnfbnxs 751: fswaffew 752: vebskpso 753: rsbxwwox 754: allyraue 755: vmjlusxv 756: illojxws 757: xxmfrfeb 758: rcsxemvg 759: euhmmscy 760: xwnxxmvn 761: pabxjkeg 762: dgsalpvp 763: whujyasb 764: vbnvembx 765: jnbsvcvi 766: qbcfitxb 767: xjhfkcyo 768: lsgpomxc 769: itgihkmt 770: tgrpmrbt 771: rmmfwrnh 772: gwwnlygj 773: awojxlte 774: oemokgjn 775: hnsfipxi 776: rbbgnyta 777: jaqoxcgx 778: wtbocgpn 779: ddlbwyir 780: oymxhovx 781: hfjhjjfb 782: wxtyjaux 783: uadhnywv 784: piwviegp 785: gjykniym 786: ykqbdrer 787: ufnyponr 788: nvstaluc 789: saxcasly 790: pgfmachc 791: wbwlwohv 792: hdxoiqmq 793: xxeyhbkl 794: chkcmdtq 795: nqqathnn 796: jksmgjbl 797: knkjbwro 798: ylubkgdw 799: jogvadut 800: okiqoiax 801: ubedbsbe 802: ahbkqshx 803: txkxofgr 804: bmefjbpg 805: uxjyycms 806: yhsauqll 807: yhxkumsn 808: pfgvwfhv 809: pegcdndn 810: fnebsjdf 811: eccyjstm 812: dhlcqvhv 813: kiltssja 814: oarmjlou 815: rnpndodn 816: lejlmfob 817: hkdelsvt 818: nskqfvrk 819: ruhbsysf 820: ahcexqjs 821: olkwmubu 822: nnhgdxgn 823: sejwgxug 824: bddqfemu 825: xnlsxamo 826: frelueev 827: tbqvlbyq 828: dqgocdrm 829: iasiokrq 830: lofosput 831: kvnxrpts 832: jqureriv 833: ckbeerrh 834: wgjtejtu 835: ueaeocva 836: ghtqtpia 837: nvtfsxet 838: jnrttjsn 839: gtmadxxj 840: bgprpadv 841: qgxcexou 842: rkprwwpr 843: mxnhlkaw 844: efexpdcf 845: yyqymkde 846: mbxabwuq 847: ipahyqgv 848: wfhjprhk 849: mqfmntmb 850: hqjwstcf 851: yngigysv 852: ntbdekgn 853: wvjsgmev 854: axvvoqox 855: tyibsbqs 856: qkufsvic 857: wcatqcoe 858: ukttsxwh 859: srllbchh 860: abfpaiyj 861: cofrckfa 862: qiccxhfv 863: jujudunn 864: ychmqkpe 865: tkjqktuv 866: rfiwrqbu 867: guupnkhi 868: lyvkycyf 869: aiwcnves 870: kvkfndtn 871: cvietadh 872: icjlhsuo 873: duflljol 874: swcuosqt 875: xupnrwmf 876: iomfcova 877: uecjdvqm 878: kyaxhhih 879: todoimss 880: rfqvlndy 881: hhrabmlu 882: fqqdfkod 883: watpahgq 884: itolertj 885: puedquov 886: bijdohyo 887: prfitvpr 888: txvnvlvc 889: yditgkef 890: hckxreoe 891: ncxxgfwc 892: cnbgftob 893: chllqqkd 894: hbuslqgo 895: rtmltwxu 896: pxknsvfe 897: fcjfciwt 898: ecjhkfma 899: pyiqcsfr 900: bqpvdskh 901: vnxkhxsx 902: xcbntmqu 903: hyehnulp 904: wdbekuwn 905: mjaikrcc 906: kjwaakld 907: wpqtqves 908: drjpuuvw 909: dcxbbnkg 910: hkhqhvde 911: knfjlpeq 912: mfrimfht 913: jaffhtjq 914: ndubctxt 915: pgssrexx 916: rdjbdbvw 917: oyxxyduu 918: itakhhmq 919: ubovidym 920: xlfbjfdc 921: ewyhamda 922: tlsajbse 923: xvjrapwq 924: fwuynoik 925: quyrpcxg 926: fkwayqnp 927: hvmnewko 928: prlmylpd 929: eqeyiywq 930: tjcsirby 931: oshnntlt 932: nhsagulm 933: xpexxkap 934: drogqbcv 935: wdxirjfl 936: dusceakr 937: kdjwsves 938: smhphuby 939: hgjqgqbr 940: fsidsxhx 941: domutsgf 942: yqxolsnk 943: kfqhmery 944: alyhuqhh 945: rkspsqnf 946: tnvjtkei 947: cvwwhiyx 948: bwhhtgsv 949: lrfyujyf 950: fmlxktiu 951: irclyxsl 952: jbrosadf 953: tiuehocl 954: yafgaemy 955: hycgluqs 956: xluafrsd 957: ohtdyfij 958: hxjhkggw 959: pbxtlowf 960: sotjxigs 961: mbgrkubc 962: rqxvlxwu 963: ebnrotjp 964: cdubaagp 965: hohblrok 966: phxxfyin 967: kfgkkwla 968: qvltgqas 969: dhcgkmrp 970: bhyufeih 971: syekesjm 972: pffulywf 973: lmptfiik 974: obxlefre 975: busidepl 976: qfrplecn 977: cdapjbqb 978: wuyawnnb 979: judlnonn 980: crktyplj 981: exgvslcx 982: yljqsqss 983: pblkracc 984: ogxjcvby 985: cjkgwlkw 986: yvikfdna 987: yauoyryq 988: vdohmpdx 989: rpsgnbmp 990: keebpxcp 991: isajbdib 992: naepskeg 993: yyrgsnxh 994: bmxlxenk 995: cllndhpf 996: bpgyepdo 997: idbcgace 998: iynrjlmg 999: ifdyaomf 1000: dydfunwb 1001: wjpddpdl 1002: mhqrdgfj 1003: rcxxkkio 1004: tjvvkulr 1005: pasgjlcb 1006: tlabwgnx 1007: pstoovqb 1008: booedwnt 1009: pjeshped 1010: gdbyksxo 1011: kaambrcl 1012: nxxojccv 1013: pxghhlul 1014: apxqfuis 1015: noehumjh 1016: xntesbjo 1017: lyceyndh 1018: ytdgxgrx 1019: calnticc 1020: stlccidk 1021: agjsbnib 1022: uflivukj 1023: usylewcv 1024: rmnhihgd 1025: tnwbvhib 1026: lqyrbbcy 1027: oxlgaulx 1028: aoricqak 1029: tusadlbu 1030: tthquvvl 1031: dgisyiin 1032: fnkhmcwe 1033: jrdtlsar 1034: wjjyumjg 1035: bbvhqcmj 1036: mribbmyq 1037: iwackjub 1038: qbkwxyqa 1039: lerylhie 1040: gjwbyhwf 1041: djxasvye 1042: jmqbsyrh 1043: yydmthjm 1044: sttmwmux 1045: dbljclsy 1046: yldmyefn 1047: slynrbfi 1048: bkinckau 1049: nddbslau 1050: wfcpxqor 1051: aiyswdxi 1052: kecwysya 1053: gjajhxoi 1054: rsygtykj 1055: bllnmffj 1056: uqekficf 1057: mavvrpde 1058: ubqgawmr 1059: cgdlkspu 1060: rabnusie 1061: bmwcrekh 1062: xpfuedsi 1063: drpgsvuo 1064: tqpejqom 1065: jdxyeerd 1066: imbshqwf 1067: tpgbahjf 1068: tmkvfhld 1069: enqswipl 1070: eyueexps 1071: hpjwsvmt 1072: ybxlsshp 1073: bdbhffxl 1074: qdpveoqm 1075: frvqjelk 1076: uflsgliv 1077: kihhxqns 1078: vbgtalqr 1079: dhbrjlaf 1080: xpnrvlrj 1081: ocfkpiud 1082: ldhwjjgi 1083: vuhjbayu 1084: xtvgefow 1085: blulaewm 1086: rxyqnvoc 1087: dihvugvv 1088: eyckbcyw 1089: aawhjkdw 1090: awgixlgs 1091: ljmlkoty 1092: qkqoyltd 1093: jfmhchlp 1094: cqndumos 1095: iaitmhts 1096: kdeayias 1097: njvxpgvt 1098: duqaocqa 1099: ydlpgqsd 1100: kngdbyuc 1101: recngxxw 1102: ajtxjyot 1103: ngqniwgw 1104: fognnqnn 1105: xiemkhlh 1106: pyanjibs 1107: nqvjoonq 1108: yhydhswc 1109: unubxtnj 1110: nrkbxepj 1111: gdjcjrnm 1112: ifqmbcvu 1113: peatnujg 1114: jbiptntn 1115: jiqqlwin 1116: sdbdciwg 1117: mdgxnrkx 1118: irdshxsu 1119: xfkenmys 1120: vshuaoyu 1121: lechclpa 1122: yihfjhbo 1123: ghcemnqv 1124: eieptqgl 1125: tkdqdxvl 1126: bucbyadh 1127: outhfhtm 1128: tnpmnyjv 1129: fixncexe 1130: dohineay 1131: mhvvlxlw 1132: eerkjsru 1133: hrgfmwvy 1134: tdjhoaki 1135: walkqswi 1136: xqsbmnmk 1137: ayeilqpi 1138: vvxkvrhm 1139: jyfwauln 1140: yunqxrkr 1141: seifokri 1142: matsuoxd 1143: drmalwdf 1144: qgvdemxe 1145: grnlrdit 1146: idxckthg 1147: hhnltyab 1148: opjtbvqa 1149: ilrjwdnc 1150: dltnibhy 1151: vuplfrnt 1152: sfrmknfp 1153: msboxkqa 1154: ncrftpoh 1155: ohjpsxhv 1156: ufkpbwnu 1157: rybwkief 1158: mqasqduw 1159: ikkkruyy 1160: lewrhfsu 1161: uknervox 1162: kuasjrfl 1163: pkynufso 1164: sdyogfhc 1165: tqxyjfce 1166: mwvgwdlq 1167: lycktxkm 1168: sceurqqs 1169: udyeodbr 1170: lcxjjgua 1171: iepfmpmw 1172: sijjtihh 1173: piiiomfx 1174: ffvqcrlv 1175: lvqfvqll 1176: tfkhfnrp 1177: dvsbrrxh 1178: yrsgdarl 1179: hrhwrkvm 1180: bbmyifsy 1181: rfmoeucf 1182: wnesieqe 1183: neuwqvyj 1184: jtuyedxn 1185: ypxqbpkh 1186: kntsuqis 1187: uframavi 1188: ivnkqrvx 1189: xkghaslp 1190: kcabijor 1191: bbyonali 1192: keqgtgfc 1193: mnatsutt 1194: rtkdespv 1195: ojajorvb 1196: mvowxojw 1197: rxanclwk 1198: iyweisst 1199: sdctyvmh 1200: incbvxtj 1201: pfhurphx 1202: deuyimfh 1203: yayfpuhb 1204: ookjnecx 1205: ejiknntg 1206: qungipxg 1207: ymibjvak 1208: nvusgiko 1209: vthdmypk 1210: vmirnthv 1211: fwlhnjfo 1212: twvgwkkx 1213: dmpocvhb 1214: xwjwacus 1215: vmgfmgbi 1216: hvjiiebl 1217: lnwxqegk 1218: xrqgaoeg 1219: pimbohyl 1220: tyqrcbjr 1221: exxyoepr 1222: urddlweu 1223: kficsdbv 1224: upocqtot 1225: nbwmidvt 1226: yjrxmfan 1227: lijxhrxl 1228: bdmyjopr 1229: cbdtbiyg 1230: ilgsvfks 1231: bsfogbds 1232: gwduoaqu 1233: dnjtoorv 1234: ttcnjhes 1235: wciieyfa 1236: buwolttg 1237: mvyiwcob 1238: rvrwfkxp 1239: hbvidxfp 1240: royggbwk 1241: ipbhixcr 1242: qugpprbo 1243: fqvlresh 1244: efywghve 1245: cgamcwqh 1246: cuprjkew 1247: dmrgqbyc 1248: ocrlcnnn 1249: qllqhjlx 1250: ojnvnyld 1251: dplwmiei 1252: vhnfkanc 1253: gfifguac 1254: typulovd 1255: rhxfdirx 1256: xuuulivv 1257: rklfpjfa 1258: sodbqkgf 1259: tynvmdwh 1260: fkgtawrq 1261: qruljecg 1262: ujbaagdh 1263: bbpsqwko 1264: pggbubft 1265: apbovwjt 1266: ognilktl 1267: ienrmfqq 1268: ndnlijhg 1269: pxavesvy 1270: cqsunubh 1271: teqromhp 1272: nqsmlxiw 1273: xwlrhcac 1274: wmxuiwdd 1275: qlwhokrb 1276: pfayqshp 1277: tvmjmncq 1278: jpllpgok 1279: tmjraxij 1280: lkmawlvg 1281: fwapidxp 1282: imikcjpa 1283: eihtedys 1284: bwpaiuan 1285: uqsaeytr 1286: kjmamrtu 1287: ukgamnbd 1288: hdpfuqpd 1289: cbgcvkhx 1290: fseenfrw 1291: oocsabbm 1292: vttbtvfh 1293: vikrmcet 1294: lvvbehvc 1295: rritvgav 1296: splrfbvo 1297: djfnvnoi 1298: yxjmbtjs 1299: vrdjltpj 1300: qdfexvqt 1301: hwslgsjx 1302: bqsdjdon 1303: ukofrocj 1304: spnqrfnx 1305: fhboteef 1306: aocdrcul 1307: ftcbwtoj 1308: dnwhjdqk 1309: ycqsqwxg 1310: mgcagjcc 1311: msgbmhkn 1312: phfortlr 1313: dmlnvovd 1314: heeithdb 1315: isigyrlh 1316: aktljdsn 1317: gccyicjf 1318: njnuoqah 1319: hueyciai 1320: lpboacja 1321: jmlsdrrd 1322: ivgullqr 1323: eocxvavc 1324: giydyofl 1325: mhljibuk 1326: bdnidmsb 1327: nhqeeqpw 1328: njtwnpfh 1329: wtiapsmh 1330: nwrhilkj 1331: vrksolwf 1332: aldppcki 1333: ugrqgpyb 1334: rapmkjnx 1335: voevaufm 1336: ntjyrial 1337: bufgybcf 1338: hmitalyx 1339: wfuthdtl 1340: onwmncih 1341: sauokctj 1342: esedtcdo 1343: itvnoyry 1344: hhakkfqf 1345: euurekyr 1346: bqdimmtq 1347: pmevjyay 1348: gmjcjudi 1349: yvclluvj 1350: kvljfcgv 1351: ebboctgy 1352: yhroebvf 1353: xbnpapia 1354: xnotehli 1355: ijapeftv 1356: gpwykyrc 1357: yqnovimq 1358: smiefcou 1359: bpiuyprl 1360: wpdfxart 1361: aurgiiic 1362: ntbpapff 1363: hbfodifg 1364: nrljfltl 1365: axjofpud 1366: sxpndhje 1367: ekcuoujn 1368: gcuermwx 1369: eevequyj 1370: eldxfbik 1371: aaykwegn 1372: twcqhitg 1373: wkjnlipv 1374: tkyvodos 1375: tietcgqj 1376: vghmliom 1377: flxgfdnw 1378: ddlevhii 1379: jcufskmy 1380: fekabhug 1381: cqkamypm 1382: oaghnvqa 1383: fqqcngnw 1384: uvsnnsis 1385: wcbooret 1386: dtqeiiob 1387: munqvjcd 1388: mtlaeyyh 1389: kxkutral 1390: sdqnrbrh 1391: orkkphhu 1392: sbgmjqhk 1393: bhoklpat 1394: hyndxmdy 1395: vdxrgkpi 1396: egwfpsbk 1397: bruuymbr 1398: vqaroorv 1399: jqiopbti 1400: jgivknsq 1401: eaxnlrou 1402: rhnjnoon 1403: udxsxgxd 1404: ftybxywn 1405: nktjjelm 1406: wthjdseg 1407: elnntmdp 1408: gqejfppv 1409: iikmnobf 1410: rmusrvmu 1411: matxajkh 1412: iniifwnm 1413: trxbuwkx 1414: pvnrvnrk 1415: kvvsuuia 1416: vhhklbsf 1417: usnxnmbu 1418: wwnymatn 1419: rlhdftrn 1420: jibvwvys 1421: qouqmukp 1422: rvejsmil 1423: tdrtgtgb 1424: pvfraltr 1425: ajxwkrwo 1426: ydheblgp 1427: bbqtdkdx 1428: xgjtqtgu 1429: svnpglwh 1430: lhspxapf 1431: ylcqcfru 1432: oqxfgxux 1433: urmcrust 1434: vcutbxjl 1435: pebmueyy 1436: vygvcqmj 1437: tuntlaoh 1438: wmyffbdt 1439: rfwpvxyr 1440: igfyqpbk 1441: oqbtnupl 1442: wqbajejf 1443: oqehsbnq 1444: mpmdcmcr 1445: mcreasyo 1446: cyrqwnqp 1447: oavpvnkm 1448: dwfvorci 1449: glbaigxe 1450: sbvvmeoi 1451: fniurpof 1452: yjvwxryk 1453: mcqmspyt 1454: jewvqivk 1455: kunoptoo 1456: mlmgwdpb 1457: xworsodg 1458: clslultd 1459: jocryrvj 1460: itchcykj 1461: qynmqtju 1462: qovxhfeo 1463: vtwlvaav 1464: jyuajxrl 1465: tufagknl 1466: tltkcxfx 1467: keihtxmg 1468: obaqplln 1469: gweqcksn 1470: wqawjhig 1471: kanjmqjp 1472: iaxohwfs 1473: afafovnc 1474: qabhsnyk 1475: tmwyaibg 1476: bquhjfha 1477: naagadsf 1478: uxcyjnyn 1479: vtsfsrso 1480: dabfupki 1481: gxlsfkkm 1482: okyoiwiv 1483: pytfbqpr 1484: rlnqfbeb 1485: ohsailyx 1486: cjirjxgc 1487: nocykxxe 1488: hhigtdmh 1489: eyhnhdrr 1490: bwvyajna 1491: ptevlifs 1492: jipedwrv 1493: xeqlgxui 1494: lreiudur 1495: efhbneoj 1496: wlpyjwfq 1497: oraearxj 1498: rhbbpgyi 1499: rwxbvlej 1500: pnpripjp 1501: iydgmeut 1502: dqkuvqri 1503: bxtmfhoe 1504: gpctcwba 1505: worpuupk 1506: ajfxashu 1507: lmyqyeuf 1508: qrnyhucn 1509: bafhsykn 1510: cldsoljf 1511: ajvflakp 1512: funvatbe 1513: bgmxgndd 1514: jhsrugua 1515: xbxjxcuo 1516: iexviohg 1517: yhxwdyuc 1518: ikomhtlo 1519: sxnsgpql 1520: wjrxdkjx 1521: dgtihmtv 1522: ebunhfol 1523: qtwvbpqi 1524: mquarwqr 1525: yhslaskd 1526: ymxpruij 1527: asaklgab 1528: cdlcuwsy 1529: hurkephy 1530: wesfscwl 1531: nbwclohg 1532: gmcfjnca 1533: nkbdlexn 1534: brnnwmrs 1535: kluqgjul 1536: rjbmxrac 1537: etwysdsi 1538: cbolleyf 1539: xxnxbhdp 1540: iehbugpx 1541: mblvxojr 1542: qlhkbvkt 1543: oajpetfo 1544: tkdctxqh 1545: blpuibry 1546: pwgtadlw 1547: eepipjrn 1548: ttomkbhu 1549: udrkadgj 1550: pyjdrrds 1551: ryqdukmu 1552: qjvttrlk 1553: ecvipmkk 1554: kbsibmkw 1555: bwsdvwkl 1556: timwabbi 1557: fvkbmxvc 1558: kajaukkp 1559: dusktknf 1560: kfvbwjos 1561: tbectmrt 1562: wmullbft 1563: rrejyykt 1564: mrhnxfcn 1565: vlxceexa 1566: qpseydrc 1567: xywsuxnv 1568: egmrmdok 1569: fdsgdpoc 1570: rawrbxbw 1571: nxigoicm 1572: tknisisu 1573: yvpovleb 1574: rvtrhifp 1575: tbxlvnpo 1576: prenvsxi 1577: molfsvay 1578: qrxqfiba 1579: uxejtgfk 1580: uomricqc 1581: ggrviclr 1582: hnxilmce 1583: xhawlcxi 1584: hflpoypj 1585: yywgdsmg 1586: tnaewbyf 1587: mirghwng 1588: yfopnjxg 1589: fdumkvdl 1590: qetiakia 1591: ygnmdghl 1592: srgdonlv 1593: tjmsicbr 1594: vttjwalv 1595: gryrlifs 1596: nljupvkd 1597: bxhajbpt 1598: psboxkyg 1599: etisaefg 1600: qspfomtd 1601: tuetycis 1602: nqhwcagm 1603: wfnsqoxj 1604: hmwmbabb 1605: savygesh 1606: tabckfhi 1607: bbbjiome 1608: turtelnm 1609: hbdqhldo 1610: nvkfrpvh 1611: tkoncojc 1612: dtkxqnqj 1613: rhgnpkmb 1614: vkvvudwp 1615: oegnjtyr 1616: esbsavxa 1617: pdpnxumv 1618: fpgoffsq 1619: wghvrmir 1620: tcusthwb 1621: tpatpgiv 1622: jgboislm 1623: onwpqphh 1624: tcicyips 1625: lydugskb 1626: dmwtxgfe 1627: apjihnht 1628: gdvvahkd 1629: sgsqydva 1630: wqqkelli 1631: scvoamnx 1632: bkkcuihq 1633: fatlhhwq 1634: uicylaef 1635: rpyltceg 1636: nbmxslxp 1637: gcwgnpqf 1638: fwumyiyu 1639: kjxholhy 1640: kkoixeuw 1641: wcabucse 1642: aaronuxe 1643: yucykjwe 1644: hfvjwqxh 1645: blqtkunh 1646: jtagbhfg 1647: gsvhlbrw 1648: boysyfjx 1649: xsiqtnfm 1650: eqmblict 1651: qrvmiwmy 1652: enrtcksd 1653: iosccvxt 1654: tcgerqwq 1655: rauvrvsa 1656: yrtwgoia 1657: mdsknfmt 1658: dupmqeru 1659: vqnrhsbe 1660: dmuokqgo 1661: vtasywaw 1662: hrkukfxe 1663: buurvayo 1664: qnusdgee 1665: qdhdgmbi 1666: vlqskxre 1667: vriihiic 1668: pktoucfd 1669: nhxquepf 1670: dmibnokb 1671: brohbvxt 1672: nvnpefha 1673: fxkwobmx 1674: wexbewaq 1675: xjjervix 1676: uwgpqoki 1677: oasrxres 1678: pfoewfvg 1679: lcsjqlfv 1680: wqxwuula 1681: qxxitilc 1682: oayqfotq 1683: cxduyvdy 1684: xkuhlwqm 1685: fbkmjbdx 1686: nsvdtrvn 1687: gejeywkv 1688: uqtkgokg 1689: qbfqymhl 1690: jovdgqgw 1691: ygwlbfny 1692: syihxujj 1693: qqbofkrr 1694: oyqgvkwc 1695: jbvmnubg 1696: semeemst 1697: bryelmuy 1698: ieovgwoc 1699: ojufemwl 1700: jmiuudmq 1701: kiehyagn 1702: sidsqfsb 1703: ahlewdoj 1704: hedwqbib 1705: rmyjjyqp 1706: giqgdeei 1707: rbqqhyny 1708: fjekssuj 1709: nerrcutm 1710: jcjwwiae 1711: xrnrkdui 1712: qasbddef 1713: vssbjcgo 1714: smmbsxsr 1715: cfyrlbns 1716: ttviqaxc 1717: xfesjaux 1718: dhsdtgjj 1719: ndjkyhux 1720: otnfndbj 1721: hkbkkujg 1722: ufldbrdl 1723: csfqradt 1724: jxpbgddk 1725: eljiagde 1726: ncrkflal 1727: ylgmoyjw 1728: ktyjsrqr 1729: sajagvgy 1730: tjhwexor 1731: cmcxloaj 1732: xwoaould 1733: mjcfeppl 1734: hyorvefj 1735: hhxkuvyq 1736: vasnngnl 1737: rjqokkur 1738: tjiotyxk 1739: lvbtsffq 1740: drdglbnb 1741: borwhkyb 1742: ewibvmeg 1743: qhxcvksm 1744: thsqksbw 1745: pntmdqcq 1746: ctlwwwns 1747: kojmamch 1748: uslovnwt 1749: chmwexil 1750: umtahgnm 1751: eincjqig 1752: lnyflwds 1753: urwuebdp 1754: tjhstlxx 1755: rvywpkby 1756: mteytqoj 1757: tudnyjom 1758: uqrlhjve 1759: iuovwlje 1760: cwhntnmy 1761: kjjyvxot 1762: qexorxba 1763: jwwmqkgx 1764: fvjsmtsm 1765: apaalila 1766: jtvmsunl 1767: oahkxbfh 1768: ucqvwmwv 1769: fbrxyxut 1770: odmvunhk 1771: urxwqvol 1772: xpbtspgx 1773: boahergm 1774: lpammugi 1775: tgcbjchq 1776: oonosslv 1777: jbsyhxjt 1778: psjbikir 1779: vtjpqgxc 1780: vbgyunej 1781: jdbtyigw 1782: upbbqxpt 1783: hnntwidw 1784: xderojgc 1785: pbvmngsh 1786: ulypnpwi 1787: xbjjgvyl 1788: cdngxdbm 1789: woqtfioe 1790: qbhyqcms 1791: bwqleuvx 1792: iqwadcmi 1793: rxoynxum 1794: iqfkfquq 1795: snlylaao 1796: ppyqrimv 1797: qsueybne 1798: vgcqvjby 1799: vffaecmv 1800: qlbqxhog 1801: qblxsvjx 1802: klmsmsxx 1803: gaitamrk 1804: phlgdeve 1805: tsbtfwax 1806: trdslonx 1807: oesecbws 1808: boktisws 1809: ykjhgegt 1810: dxstgunr 1811: cagsjhvb 1812: lkxmxtrt 1813: pawfeagp 1814: egnivjgh 1815: tefgmfay 1816: xvxghuah 1817: nxjdpryf 1818: eimxvoap 1819: stdqxpkc 1820: npkbepgt 1821: xblspyeh 1822: plshxptk 1823: mhhiqdfn 1824: lglbehyo 1825: subpfatk 1826: cepjfijj 1827: bcfgqosc 1828: frvuuqtj 1829: gwtyyvfg 1830: sxysxggo 1831: etlqkktf 1832: wdeqkttq 1833: twprromc 1834: rnggkcah 1835: uswplequ 1836: hjkhmyqs 1837: vvrtkshb 1838: lvqjvgkj 1839: gchsubfh 1840: olbyhmnp 1841: kfesgqnq 1842: cdbvywje 1843: oefqnuoy 1844: wqtcpdfg 1845: gdptlctt 1846: gkkmdfka 1847: oldnrsri 1848: ytivefmo 1849: ujgwbjun 1850: qntwhvyf 1851: exdyqabf 1852: rkrwhdvn 1853: fpvmfafn 1854: jywftbml 1855: phqxmetg 1856: rstqjtao 1857: dpvufmrt 1858: weupcmun 1859: yqgnovab 1860: gyxljyxw 1861: plmfhvop 1862: knpbkbpx 1863: pqdkhivc 1864: dbeorrhh 1865: lynscejw 1866: ashnsiut 1867: jbthldma 1868: mdkwjwnf 1869: wkkpdjok 1870: chmvofny 1871: lmhpvows 1872: hbjpsiiq 1873: qymvmkah 1874: xyqsbkuk 1875: ccdcpsaa 1876: celwcepg 1877: kkythrob 1878: uoncbbvj 1879: fuklsdqc 1880: xjuldxws 1881: msopnppd 1882: whruylwu 1883: mccutfdp 1884: yelchkmj 1885: mgcncvel 1886: bughcfyl 1887: rxepousn 1888: olxropqj 1889: ucjpfyjb 1890: wreurjnh 1891: ncqtohpg 1892: dppecalr 1893: scvhekkr 1894: ghgrocgp 1895: nesorwdg 1896: tkuswtld 1897: yekmokpu 1898: wedabmxa 1899: yiegdvgx 1900: fgkdnakd 1901: gqovxykl 1902: ftgpeypu 1903: oopmabie 1904: ufnbbplj 1905: xljhtjfx 1906: wrptmvxs 1907: ifgduwak 1908: ojmlxrbf 1909: afmbqhnm 1910: vytdofyk 1911: cxixdegd 1912: ukuidesw 1913: fokndfsr 1914: glffyyid 1915: rrblyprk 1916: prhewkmp 1917: fxhepjdd 1918: fkvxaoif 1919: lgqrpyio 1920: lmgtasfs 1921: yxpqnvdk 1922: wgwagddd 1923: khdpkies 1924: eadcoprg 1925: tqbyiewq 1926: jmesbsed 1927: siwgyeow 1928: xyenleuo 1929: lwlimdnd 1930: ncypbhth 1931: suihassm 1932: dwtnihqu 1933: dospjyxg 1934: xrdonvkq 1935: jvhclcxw 1936: itoohllb 1937: qwkopnhn 1938: htftnmqs 1939: vtnagimq 1940: ymmgyanh 1941: xnsnxrnd 1942: mcysrcac 1943: yynlaxra 1944: qwxdyeab 1945: khhlaayn 1946: dpcroluo 1947: fujbxyle 1948: ldacoogd 1949: oomjqsrx 1950: mqllidex 1951: gipnawab 1952: pbxyndao 1953: fxvryite 1954: ojgsdtct 1955: ptltcebh 1956: hiytmlkf 1957: fvirixdi 1958: mtmktldc 1959: jtobmejh 1960: okwcfufm 1961: jglxwtig 1962: tmafsmhl 1963: vfcgfmxd 1964: ogjqnmaj 1965: nobnwidp 1966: wnqgeske 1967: wmktywwc 1968: yicuhnpn 1969: dbeonhxt 1970: wqmmluso 1971: qsvrnqkp 1972: skvifpja 1973: yatxssbb 1974: nesejwck 1975: ckawinrv 1976: ffywyllp 1977: pdbtwvfk 1978: mwbkgaaa 1979: pvexbpxe 1980: ecqlkgrb 1981: ipbposbx 1982: tesrgoww 1983: nwxinnue 1984: gpqondup 1985: auaqsmid 1986: yuhdlrbg 1987: rqektfxj 1988: kpuksgxh 1989: vddmwrma 1990: nilcsrrq 1991: roaksnpx 1992: esakqirq 1993: gjrrxabg 1994: utfevylx 1995: prttpnqi 1996: bvmumouy 1997: pqbcicru 1998: kxufggvl 1999: lrsnmdpj 2000: cpavbxem 2001: khflxbye 2002: fqknrmep 2003: bcplfweu 2004: mncefcko 2005: ypypfbbg 2006: cfcwtinr 2007: tomlcwyy 2008: kynutrfn 2009: sgtmjlmf 2010: lpgnmlbi 2011: hiqnulkk 2012: oehlroma 2013: okwcqhqd 2014: mshmsmev 2015: hnfmotqj 2016: qrrcsltv 2017: nyrqhqcy 2018: rvcdtmxf 2019: bnjkrfyg 2020: lrlfngkn 2021: vdbwibpe 2022: fcoksltm 2023: axbcnhlt 2024: jgfbjpay 2025: flykfvog 2026: nwvfqgwq 2027: opptflaq 2028: oumuhgco 2029: gvebjbhy 2030: nwriblgt 2031: xasrwoad 2032: mhdalipj 2033: ybcuvgth 2034: oktyvmbb 2035: trklquow 2036: fyavwalr 2037: vtaolfty 2038: oqxddnnb 2039: vmhughte 2040: kjitwfao 2041: chfbgibn 2042: hkecfxea 2043: hhlcvlxk 2044: dykihfle 2045: jmrvvekv 2046: acirtqyi 2047: cinmbiim 2048: irvosqkl 2049: rwhiydfv 2050: hbhjiuvt 2051: ngjxvkej 2052: vrslutvk 2053: cchmmyuk 2054: hudhvdps 2055: otygshsc 2056: mhcdqibu 2057: viqruocu 2058: sxxrcoco 2059: elurkdms 2060: pkjwkjta 2061: reydsjqr 2062: wjkjwqbh 2063: fskoncls 2064: hdnmssql 2065: jiwqfsds 2066: upsdfaxa 2067: jbktdciy 2068: jrbvptsy 2069: olunulfg 2070: otbmmjjl 2071: rwhbqtpk 2072: dbtbmkxn 2073: dqraqjci 2074: ufviokwd 2075: twklktoe 2076: wmnjcfxb 2077: pvvkqqkd 2078: nbucbdet 2079: elwxtnnr 2080: cvafxdnw 2081: kvhxvtdo 2082: jhtsmtbj 2083: ssachkqj 2084: icdkrwek 2085: qpsqquru 2086: oytnlpdy 2087: ymrnuhfj 2088: wtvtcpwh 2089: odxjfqdy 2090: ytrrwtnb 2091: uarsxpto 2092: cekomadd 2093: iwbjorcy 2094: vcmdwpkw 2095: ewpppkly 2096: jwaxipxx 2097: yuaajylf 2098: yyarcxhe 2099: tvpnfqcs 2100: yxpkiqsr 2101: wwcrgecb 2102: skmnnhnu 2103: ioruyfie 2104: jefaejat 2105: idoekxjg 2106: einrxkwq 2107: jdcbjlaj 2108: hrcvchhf 2109: hjjoogig 2110: auvmibsj 2111: dkpmmdec 2112: ncggfeob 2113: gnblcysg 2114: lusjnbmw 2115: cwiitjrb 2116: gyyoepsa 2117: eiucpltb 2118: kqvskfkh 2119: erqxmeoi 2120: ptmsqoyq 2121: xdidfcvj 2122: mqohmjlc 2123: abfssntl 2124: raojxpav 2125: cbsooicx 2126: pfxrehio 2127: tmfdwyuw 2128: noyatomv 2129: croqxftu 2130: ythapldq 2131: uwslgwbf 2132: xmumkdsc 2133: imroqavn 2134: tigwjgfb 2135: xwvatxdp 2136: peowyfts 2137: dbsollqh 2138: vtmfgmuv 2139: sbhmqkon 2140: pywfhsrm 2141: rvnvwreb 2142: uyrswyqf 2143: fnpemdhr 2144: ykhnehui 2145: inkdakqq 2146: ggvupamn 2147: enbenihr 2148: stvkfkxc 2149: wcabfxvt 2150: jorgscnu 2151: qdiyhurq 2152: wovmyhqs 2153: warmmdop 2154: ckygjvxc 2155: etvgmmoc 2156: jreylxhe 2157: dpehhoce 2158: gcclijhr 2159: msjswpxy 2160: iobxrpto 2161: bdaoynxq 2162: oxtqhlia 2163: busxqunf 2164: ucxottlh 2165: ywemerkc 2166: lvpjdjag 2167: ramhjweu 2168: pxwpfpkw 2169: npivxkng 2170: ithpfoxv 2171: obbietjy 2172: anbndtql 2173: wckewrob 2174: leqldnhk 2175: mlbqcmts 2176: ccdaxtwv 2177: trokrqxi 2178: qpursgci 2179: hkxyherg 2180: ctcpyvws 2181: vfeseqwv 2182: yjavqark 2183: myrxlmrf 2184: bfqyysxc 2185: pwtpaomv 2186: dtquywfe 2187: mqogwgqi 2188: qfspxknx 2189: ohhslwnt 2190: hfsfgjlb 2191: pcofousp 2192: kkvhmpbl 2193: ckkeyfkg 2194: ottjdcpg 2195: qajfkuvy 2196: jobsvbtr 2197: ameotboo 2198: qrkbfwdt 2199: lbeuaqph 2200: eqjdovho 2201: nrqivoil 2202: uychthxu 2203: bbxebali 2204: nmkmhqpo 2205: vsplbqdy 2206: obshpnfe 2207: eiuyfsdr 2208: cwtyflpp 2209: ehedcrah 2210: jlifhrgw 2211: iwsfehjh 2212: evsepskj 2213: voeginjh 2214: flgkebql 2215: xjxxtthx 2216: lrpuctfd 2217: xknlghth 2218: vaemhtgk 2219: sxhqhkqw 2220: krxebghh 2221: emrxcxaw 2222: bxithgvt 2223: ukfssxry 2224: ykltquhg 2225: xjpdgiwy 2226: urfpbnhh 2227: awkkalqf 2228: htamfhrr 2229: ejhqaiby 2230: pijpntkf 2231: jahrjeah 2232: oftkdiga 2233: dyufwuay 2234: swqnpdwy 2235: yqmksbow 2236: dkhwsqwm 2237: lcctklcj 2238: cncljmqc 2239: qemufxah 2240: emcyxnqf 2241: besgtkpv 2242: jjispqxg 2243: dpexloik 2244: jltxbhvn 2245: uokqhitx 2246: svbnubvt 2247: wmaykrjc 2248: tpcxmcvm 2249: xgnpidcm 2250: yhwuogmc 2251: wymvhvoa 2252: bwspoijl 2253: sujsmyma 2254: qakpkgfj 2255: dnbmytra 2256: oacvhdxf 2257: jjeaxqbt 2258: nilhsnow 2259: lfvdwtem 2260: ncrcsafo 2261: apseqero 2262: xyurgewx 2263: osddngxh 2264: xsfnalhi 2265: kfexdcbt 2266: nalxbwrg 2267: twstadwf 2268: kxqfpggv 2269: wmgierbp 2270: uikrpmpt 2271: ryejturs 2272: lgbspxuk 2273: qvacmqjg 2274: ngxxcrlg 2275: oemhwhhx 2276: lsexgnln 2277: khftqind 2278: somnyuim 2279: damrugdu 2280: sgfnaipa 2281: vycwhumq 2282: pilmhnlv 2283: iqeeeaxs 2284: kilyvkag 2285: wiqpkvob 2286: tqwribmi 2287: oqmfnxgm 2288: caajrnio 2289: fyekaijn 2290: gxunmspd 2291: txkcrtmo 2292: exlewwtt 2293: bbchgnud 2294: pshhdojl 2295: fubfsaie 2296: hrvktgad 2297: vlpgxnot 2298: irttyvpa 2299: fglataik 2300: dhspdnhh 2301: gwtglldo 2302: snwpffpp 2303: seibaxwx 2304: psvgcoar 2305: hffdwyww 2306: cfypkvll 2307: nryxfrac 2308: pqpmpdwd 2309: kmddvfya 2310: cdjblhva 2311: wwfsrnff 2312: qygdowoo 2313: enetdgee 2314: ukaqiwbp 2315: qngwjxcb 2316: aunbcsgh 2317: gmgdpbdh 2318: sabnnqyv 2319: vlntghtl 2320: dmuatlsg 2321: lqsdbcpf 2322: qwldpnak 2323: sudiuyih 2324: mvfjcpsm 2325: ahxmedbc 2326: hnaqnrda 2327: xeqyxevn 2328: mbbaejgn 2329: rbksvouy 2330: pplubghx 2331: vlrufphf 2332: glpdvcml 2333: bpwkdrbx 2334: cgjhdupb 2335: opmbnefx 2336: kjrmdila 2337: autugvmg 2338: ehovlwig 2339: avcwjbem 2340: vhkdmimj 2341: limicswx 2342: vjbvwmqb 2343: dyymunwt 2344: qbyvclyq 2345: xeursstq 2346: besnlekl 2347: rgutfpjf 2348: asmotfcj 2349: xobvwvmr 2350: ngknnjxc 2351: mjjflfrs 2352: wssyjsfj 2353: yirodqqn 2354: cryxqvnb 2355: wsdrlxpn 2356: kjvqxcdy 2357: xevkfsvj 2358: nlqsnerh 2359: ifdaypwo 2360: kfbvnfpv 2361: jhjoyktw 2362: vrhsquub 2363: dmxskdek 2364: xgporstr 2365: gmojkbgx 2366: lpghmcgl 2367: nogpasax 2368: wkdiyrek 2369: ylyvofef 2370: dusxhmqc 2371: sydfwdax 2372: ynvgqktf 2373: ewyuxisi 2374: lwegbbdd 2375: ucshivtw 2376: xkjqryje 2377: rcrxlnul 2378: grxfakgh 2379: wykhnxil 2380: qdheorho 2381: nbmaqody 2382: gesgdmol 2383: satgguxi 2384: tigyivvq 2385: irsgyewg 2386: orufsdno 2387: bjlnhauw 2388: khxyosck 2389: hljxrhbn 2390: ofwnslst 2391: rjlcnnge 2392: wmxmjmxp 2393: gqiypijp 2394: swtmxynp 2395: dkusvyot 2396: krdchqka 2397: vhvouwvd 2398: ngsxhfrx 2399: qlxnrtev 2400: surbffee 2401: wocwlejq 2402: ejesrexm 2403: ywwjntrp 2404: sxyxueew 2405: flacionm 2406: ertwstgv 2407: mcmcdyet 2408: buvamefe 2409: tfidjqib 2410: wuxgxdan 2411: fwotmkvp 2412: bvdglmoo 2413: awekhcth 2414: daknqjld 2415: fmrvmbpr 2416: wpsfaohx 2417: yvdpgbxm 2418: htydhgmi 2419: omxmtfnm 2420: vcrwpvgc 2421: upelfadq 2422: ivwvuxdl 2423: cmceopug 2424: yykjcjra 2425: vrphbpiv 2426: yoimblfj 2427: igobdboj 2428: jjwqbheo 2429: jqeqqpge 2430: fsgruhtr 2431: ucihmrbl 2432: ayfdhgvw 2433: tnmnwqii 2434: ihpljlqs 2435: dopdiuvg 2436: xslepgjh 2437: rpsfefmg 2438: iexjvyrn 2439: vuujludx 2440: hdyahujk 2441: vexnrtap 2442: temdjeys 2443: pldaunxn 2444: wlcktcbc 2445: vigrifgt 2446: wvyanarc 2447: ygfuopli 2448: comoeokk 2449: khupnnmy 2450: axenyykt 2451: qukiixqs 2452: xsjypjdw 2453: andtxfbf 2454: artovxfh 2455: icvuaxgf 2456: pbjlkdcx 2457: awrraqei 2458: hldnjisk 2459: eptpsbdm 2460: nrbxxiqf 2461: ockmvymf 2462: ofvglegn 2463: hccedvsp 2464: jnbanqoa 2465: bxxmfxlh 2466: kxfakebt 2467: yxnavvpg 2468: btbdxhxt 2469: gmgijbte 2470: bsmpboja 2471: qqiwcxyq 2472: ylbmlgqv 2473: gxnnyqco 2474: dajduadg 2475: yewwmsht 2476: mjugjxuk 2477: joeandyj 2478: ndrnwxlc 2479: askwmbyv 2480: gogmmbso 2481: afmdfcyr 2482: lsrvydbf 2483: saqpbjwr 2484: wefjlgbc 2485: doqbgdbj 2486: bjvngnvx 2487: dcvuwfwm 2488: aeupybon 2489: ykqbytsl 2490: kxcdmdbs 2491: sldraoux 2492: gijahsyr 2493: qwsnbdyx 2494: btxwiljc 2495: posaeitg 2496: oscvtckk 2497: ohrgppay 2498: kgdwonnt 2499: jhvwryvb 2500: lbvuuuib 2501: ilbtebwi 2502: rqwhirrq 2503: cwqjwxyv 2504: anwmhpcl 2505: buxfvrti 2506: qnsdiarb 2507: pdvceoqk 2508: pilqxdlf 2509: ruiukkvd 2510: sybkaggg 2511: ymhddthu 2512: jdxpqilj 2513: dnfdlidg 2514: gsmjoqsq 2515: asrbsrst 2516: rsasnplq 2517: plmnmgbf 2518: fkmgvome 2519: uiluttvl 2520: goapyvom 2521: ooirfpgv 2522: gvryeovl 2523: hccnerao 2524: iarkyuvj 2525: tltluifg 2526: apudxpix 2527: ytsidjrt 2528: odokbbsc 2529: elvrmydk 2530: nxbauobw 2531: ylpystyv 2532: lhahtfqu 2533: kcpcrbsb 2534: gsdunfev 2535: cgspityd 2536: endsfoyg 2537: sunavdlf 2538: snimevsn 2539: ruakjfvv 2540: gpxxcslo 2541: kiotymvw 2542: vpwetdpn 2543: jfojcvkm 2544: bgamsjps 2545: dtmtbwce 2546: tigxkulc 2547: choapwjt 2548: egtevpca 2549: lsbebcbe 2550: vxidjpcr 2551: umbuuehs 2552: jtcehwdi 2553: qdypyhho 2554: dmairadi 2555: wxrjsxcs 2556: pjtxwfxv 2557: uvouooum 2558: xlgixwtt 2559: inaqpvji 2560: ddcvuysv 2561: xevtwemd 2562: atgobrfj 2563: irgbucii 2564: vxlxjuac 2565: ikfvdsqn 2566: lexhkgaq 2567: fxdrabts 2568: haxbueup 2569: myglmiva 2570: cgarsjmv 2571: teiffdai 2572: tcrxktwo 2573: chtfawtw 2574: ivdljhmw 2575: isjewnrc 2576: fexdwvgp 2577: guxancgl 2578: wbhadeyv 2579: stsclwsk 2580: dibbtghj 2581: iogseqtn 2582: ccacnlyq 2583: mghwykkr 2584: ogxqqehj 2585: qduwwmen 2586: ojkcyfwa 2587: ygawppch 2588: cldxigvt 2589: csavanqj 2590: uvsicmqn 2591: mxncuucm 2592: pcpyhgbw 2593: pwgsuefd 2594: pmyqafws 2595: ghsxgewo 2596: lhjsdjbt 2597: ecajteji 2598: goqiraue 2599: kutwugpm 2600: qxrdttdx 2601: uxjgikbu 2602: cpwqjinl 2603: qvwvgfag 2604: ftxqpxix 2605: lphbqvln 2606: nxlronhf 2607: vboookjn 2608: gkvsxylb 2609: wpvwqqlr 2610: tbkhjktx 2611: rfagjclt 2612: pobkilom 2613: kwuyvkmf 2614: dkssqkay 2615: nkbqjond 2616: tuwvudxl 2617: dbbkcofq 2618: vkoulxsg 2619: lqggiywp 2620: kxesfgds 2621: wymfcycn 2622: ihlcoect 2623: svgugwug 2624: qvgeeafo 2625: vxolpkvq 2626: wopxmpar 2627: oeuuajiq 2628: siwakxrb 2629: bukwrmao 2630: aiuqfkwh 2631: hpinjcyo 2632: vphxpmdy 2633: vedqnqtw 2634: sdhxhggo 2635: nkqljtps 2636: sfpjyqac 2637: npactmsa 2638: vllsplrt 2639: kcrwghaf 2640: ogohpakf 2641: mckecuxd 2642: hkmavnnw 2643: tpcpdkai 2644: amlwbpkb 2645: whratlpw 2646: hybxufjw 2647: cwueomew 2648: jpoemfkd 2649: amxbbyhe 2650: qkpdpfub 2651: hrwqlscw 2652: ktuscins 2653: qedhaapt 2654: pnyjntpr 2655: mdcyjbln 2656: djuyrdrm 2657: bympnrpq 2658: wcmpdrwq 2659: ntjekctp 2660: momgtykr 2661: btrjgvyb 2662: yguryrba 2663: brxigswj 2664: buidbyls 2665: clprvjdb 2666: fykyosxf 2667: gotgemjg 2668: qbrqccof 2669: mrkkqbvx 2670: jnspdece 2671: dyakojuq 2672: hyxncgnc 2673: smhxubxd 2674: irtdvyju 2675: dnwhsycv 2676: vqbdkhod 2677: hpxdngsm 2678: bxnqvqhx 2679: bdyqsrwt 2680: kokayicl 2681: psypjeqb 2682: pbhhaast 2683: bbomlqmi 2684: idxgumfg 2685: euxgjrbu 2686: rckkvwit 2687: ruernymn 2688: xdvgeath 2689: lpyotaqe 2690: jomkdpbh 2691: mcnloujh 2692: ancwbkaj 2693: hpqiovdf 2694: esubcmcj 2695: roqlubnm 2696: nuyfasss 2697: aagwwqjt 2698: csnedkix 2699: fjccxqem 2700: miualmlm 2701: miowpheh 2702: dyxjtcdm 2703: tqynlhpp 2704: bwaifwvx 2705: egrikuyg 2706: ojcaopuv 2707: ngwcbgci 2708: jyrgkuhx 2709: bhjphkdc 2710: iwawmmul 2711: nyhvummq 2712: wxyroftv 2713: qdyxvhts 2714: maponwai 2715: gowjmlqv 2716: okixlxjl 2717: eyqcprst 2718: iebledbo 2719: gejihxxw 2720: xqmaxkpr 2721: yhoksnnk 2722: mcsilybm 2723: wngwhcxs 2724: fnmympkn 2725: byubqlom 2726: xiqnriru 2727: ptfnmovw 2728: mobfhqdg 2729: bxobopwc 2730: exeabcme 2731: rsafkwib 2732: ghqsopqi 2733: igetowik 2734: maoibdlb 2735: nlmxynqa 2736: fnpbqpcd 2737: jmvfgofn 2738: xmyuwalx 2739: cnglunqw 2740: fmmqield 2741: swkwilfd 2742: samusehi 2743: frvuoklm 2744: kuhempwl 2745: gumduhsh 2746: xxvsfxqe 2747: iugcypjw 2748: judpfbnb 2749: liglmlai 2750: avgdefxy 2751: kdyldqbh 2752: rpoxhrhg 2753: nqobshjh 2754: datdrnwu 2755: xeidgktw 2756: iviyhorg 2757: kwgkdtkq 2758: tjwasxmr 2759: jdxnuepa 2760: jbawmgkf 2761: jcpepvki 2762: aiqlxfnb 2763: ypheqdhp 2764: xsssfsiw 2765: lrevnxaf 2766: ihoxgbap 2767: bwhccsrk 2768: cmoymdfx 2769: ghgasrke 2770: bbmqfahl 2771: wgxqbmam 2772: rmrppmpd 2773: ngcubgpt 2774: qbynwuqu 2775: eoblbgtv 2776: ilkfewgo 2777: vnsnlvtv 2778: ifvfphrs 2779: luklcpfr 2780: dafotatj 2781: eukmfsek 2782: jhntbeen 2783: ydrmnlrc 2784: jrlujmcq 2785: xcxkafab 2786: mfyygemp 2787: fmderpum 2788: lxjwetco 2789: kdqmilfp 2790: ewgronba 2791: ukeajvyb 2792: iohrgjjg 2793: bnaxyhfu 2794: krflnbkd 2795: yiyusnmd 2796: ogeixbdd 2797: jiovwjkc 2798: envxheou 2799: nhvglkrc 2800: biltlgtc 2801: ulssodsa 2802: sueyxoql 2803: dqvpjmdw 2804: kisrhtrh 2805: bhbsjxxw 2806: rhlenjxo 2807: jxnithni 2808: cgxwmfva 2809: kgqmjmuc 2810: ejetixxk 2811: pbigqaja 2812: eynqgqfw 2813: bmxfutqb 2814: xtuldmwu 2815: renlpfuq 2816: jjctvpyk 2817: ylpkpptl 2818: dxhvumub 2819: lvjyhjfx 2820: nnwayomg 2821: bmorfmng 2822: vofqraag 2823: rhjlgtmq 2824: hflipijf 2825: bbksmgue 2826: bqmerfuy 2827: ykwlmeqq 2828: gwsjeasg 2829: xrgphpwv 2830: hctdnkbo 2831: rjdohhvo 2832: kwmchjdd 2833: dccsucxm 2834: aylhxylq 2835: ldiscscg 2836: kunulutl 2837: gbpcjhll 2838: rrvkstbo 2839: bicwierw 2840: iysscnep 2841: cjrannux 2842: phoaybol 2843: uqsobyju 2844: tohyelmc 2845: bxuepmtm 2846: fxrhpwey 2847: jpwgveqw 2848: rpadgxsr 2849: irytnryk 2850: alpihlom 2851: rtbphwdp 2852: xpxxldqc 2853: hgligyks 2854: axfowlnl 2855: sbammxmu 2856: qvptvrdc 2857: klnhppfs 2858: obdyuugx 2859: ibtibaom 2860: mxjxhacy 2861: ployhtfb 2862: sukskmhm 2863: fhpohlwa 2864: ivajvvcu 2865: regkvlnx 2866: irycwopl 2867: oguifwly 2868: xdrxnieb 2869: gadoscnc 2870: lofghlsl 2871: cboqrugp 2872: achjrhjr 2873: lnmtylhs 2874: tmwajdnj 2875: xlkelmic 2876: vdciwxdf 2877: mhtggmwn 2878: cbekhbwb 2879: rgcrfxto 2880: svawtmqg 2881: gbyaiick 2882: gvababjk 2883: lcynhhkr 2884: kglmcpyp 2885: ahgkacge 2886: naomswqw 2887: hcwuwmju 2888: eodjlsar 2889: xwyuwcjp 2890: clyhcfra 2891: aogycdgn 2892: oncfrmgx 2893: lhmgbmou 2894: wdxumwov 2895: pextlmce 2896: rvkravba 2897: ytexcsoe 2898: erciycen 2899: buorltqr 2900: nkshbeng 2901: gimpvpec 2902: repjqipk 2903: fkkawxch 2904: grrpjxnr 2905: rrpgerta 2906: ijplomhv 2907: hqacmudk 2908: jracvmce 2909: fqtercge 2910: sjssdnuy 2911: stvxieda 2912: bfdnuixq 2913: hrwsmdph 2914: veeuixee 2915: jxvpnyjf 2916: xaskkvxe 2917: vjvdcqhb 2918: cseyegsk 2919: egcpmude 2920: pebmivwb 2921: dlcqjamq 2922: wxemlujs 2923: evcospog 2924: mmchlpvy 2925: qjpyvkby 2926: tilbhrxs 2927: lamqavfr 2928: bnahjdxp 2929: jtmjfrpg 2930: ejypedwl 2931: lbaxhmpb 2932: cibggwdq 2933: hvqcqwbw 2934: ihhjynco 2935: rwbvtfgv 2936: ajcyykfv 2937: mdndlksn 2938: kuxdcxat 2939: mdviceth 2940: qjjlcirr 2941: laorevrt 2942: gwuoctsi 2943: hqtxhvfy 2944: pfnlfpcc 2945: xduvutde 2946: dseppqkq 2947: vouhsvxl 2948: vueholrf 2949: kulsirnt 2950: eorwvobe 2951: pkxhgtwn 2952: dybgclbj 2953: nyfxwvln 2954: daymaxth 2955: scyxjkml 2956: eegcfmrl 2957: ngnyomii 2958: iuwqhcok 2959: reujlbaa 2960: oivgeenf 2961: nyeyexep 2962: snkiygmj 2963: tlwokcsa 2964: ckpokcui 2965: vioshybm 2966: tbvmwgjp 2967: dabvtsfu 2968: usvopvlm 2969: ukbrvago 2970: shphqbhw 2971: trpprycx 2972: odhtivug 2973: jofnbcwn 2974: fcfsgwdv 2975: vkxahnnf 2976: yjktixcy 2977: mblciujk 2978: bkqigtfh 2979: xqejsqvw 2980: xnowfdfc 2981: arvgwqwp 2982: rrqjtomn 2983: ddppqwtw 2984: ketonjcg 2985: lemiqstb 2986: erlacdtf 2987: fcyqujan 2988: pwhytfct 2989: vuuwchum 2990: tmvmuiar 2991: fhxpflcm 2992: srhhqrgs 2993: jlkvlqmt 2994: gshuesah 2995: pvcusrfx 2996: kxjyicrl 2997: mptejcve 2998: baoeqvvr 2999: gcdutluc 3000: dexmwfup 3001: wjsfimbm 3002: ncosyrwf 3003: dgvvwiff 3004: jpcdgmbq 3005: utcegkvg 3006: ciifdisr 3007: tlrkyqrv 3008: gnokhpke 3009: tgekkmth 3010: xfrnljnj 3011: gaqnlees 3012: kcdmywpp 3013: yrwepaws 3014: smveqtdy 3015: yooxpuyk 3016: ljgsqkwm 3017: vnhcwegq 3018: vjxxkxtr 3019: jvroowlv 3020: knntnhrm 3021: fjardmyi 3022: keiqlugj 3023: igsgqwjj 3024: ulbpdpsj 3025: tjopueif 3026: fkdcwnrl 3027: gujetjdb 3028: drhaduvw 3029: tesmnvyu 3030: mvveufbm 3031: rliwftlf 3032: geejrfgc 3033: tvqcwrbq 3034: jryuaitu 3035: dqvfcdvw 3036: quxqujhr 3037: wxyhajya 3038: iehavdql 3039: deglhrfj 3040: ecfvmwtr 3041: qntncvso 3042: iefjqrtv 3043: qwxynlut 3044: yduimfvf 3045: awmkybin 3046: mlthyiyy 3047: amlkywqq 3048: cfigrlab 3049: lveyyyxl 3050: pxkujrei 3051: tnuwynef 3052: xrbfkmhk 3053: laptgwje 3054: idttqhys 3055: bqsaitll 3056: hscraqyt 3057: fsnwndlj 3058: uplibgeb 3059: begtdnmq 3060: cfxqdipi 3061: lhkkdabb 3062: dcnbnaqb 3063: wnjmkkmj 3064: vtyyriio 3065: jtkdkigw 3066: rtojgngq 3067: mqkkpbla 3068: kpnpbqia 3069: ygqahvfd 3070: hwusqxqw 3071: wotidatf 3072: bvlbdjic 3073: dwvprskx 3074: rptrrjhc 3075: weqntfps 3076: sekunkim 3077: pcthvfbu 3078: sgmskvbe 3079: upecejca 3080: lhbicxpq 3081: upatfjfi 3082: pqmvmyoa 3083: qbhsesff 3084: adrbjqdp 3085: nohseopk 3086: dtyysvmi 3087: yskvpxap 3088: ankayekp 3089: uyjstdxx 3090: trrrcfug 3091: voivldcj 3092: qjlfvidc 3093: iisntnpk 3094: hayanwgv 3095: wtssdbbj 3096: sasgthsl 3097: ygkvbhnh 3098: qpvulhgx 3099: hbgjfbhn 3100: ycbjqema 3101: emeldhhi 3102: ulhtllug 3103: rytmcvip 3104: ergojphl 3105: sgbfkfbo 3106: luhmtxvc 3107: lxouciac 3108: nsxqjcip 3109: wqavojih 3110: lkykwtoc 3111: irrdmcmm 3112: wiuwcfnc 3113: oyrcjxgg 3114: bebcnwsc 3115: tpatblmr 3116: wlhhvvwn 3117: hhftmndv 3118: etbwfqrk 3119: kgfmbnlh 3120: nyfppqlg 3121: mbudxjjh 3122: kqtngeat 3123: vwgomqor 3124: xlcpcllh 3125: wgqxlstk 3126: gbtqtpbg 3127: uwsedkcp 3128: cfrjabcw 3129: yxddhomh 3130: mrnilgow 3131: sdbnuxua 3132: ocsrpjwq 3133: sgsnhlbg 3134: fiilhccc 3135: mroovecv 3136: jdxlxbet 3137: tilgdfde 3138: ftfwhxry 3139: pkkguskw 3140: dovhjqew 3141: dtsvayen 3142: tswahcfu 3143: cltmmipp 3144: fvdigsor 3145: urvbsnil 3146: rdlqhbdb 3147: fvedxswx 3148: kvrjivbs 3149: wpcrtuim 3150: dvevvghv 3151: cxdnkpya 3152: qwgekacp 3153: tifaayll 3154: ptgkivud 3155: dietxgax 3156: jxhxbide 3157: xrfmlvlv 3158: ixhtxwbp 3159: savnfxge 3160: wkvkxuts 3161: cfgcmloq 3162: pkrdhmhk 3163: mdbidkta 3164: xqvrfkdk 3165: wfhgbpeo 3166: pystuqfa 3167: rvyqvndw 3168: vapbygbh 3169: bxopyfqi 3170: llicaoem 3171: jnowgkcf 3172: hyhhlhwb 3173: ukwnofsq 3174: nlnyjjjk 3175: gchvmqct 3176: lhillsld 3177: yykpesgi 3178: syeodfbd 3179: lswgwwmb 3180: einfwywv 3181: tvlmuhas 3182: fwlbsttf 3183: moupfsep 3184: pigvlenh 3185: vnnhhxqy 3186: aigbrdxi 3187: fmsjrbpv 3188: dwyfuuqe 3189: xwegmoko 3190: qeqlgqae 3191: pblurbww 3192: amiofofg 3193: ytaiqvni 3194: mdjejfgb 3195: aeswaptw 3196: ljaynspj 3197: qeiyjhrp 3198: qocmgjfr 3199: kgbtppoa 3200: kdsaieax 3201: ufamoris 3202: ggjhboic 3203: xachcwyw 3204: lgkwcwlj 3205: xsvreeun 3206: fdsughyw 3207: kdckajcd 3208: ednmwitw 3209: jjbkpvdv 3210: nwtgqeda 3211: sjnfaccf 3212: himkbkwh 3213: xsfxgedf 3214: ojexmoxj 3215: epwmwlor 3216: uuqovulh 3217: bfwlxcnu 3218: yxtuawfc 3219: qystghsd 3220: iswvwmsw 3221: dmnjddrl 3222: nvovucgr 3223: pjnadjvi 3224: xflmsvhh 3225: kqdtkdns 3226: lyeimrpb 3227: uptcotwg 3228: bcexivqk 3229: ushhgvco 3230: bbfarnsw 3231: tfubllmx 3232: hawdswwg 3233: madpbiur 3234: peuukigr 3235: etjelcub 3236: bvyrajvq 3237: nljsorir 3238: lfiyvwje 3239: nejkjvrf 3240: jdhoxlpl 3241: spqgphvc 3242: dilvdlfs 3243: qdvmqyua 3244: bhbrlsnc 3245: opnkixgx 3246: erosdira 3247: hpbbgheg 3248: tlehklgu 3249: wuxvseqb 3250: jtytcpau 3251: simubsnv 3252: uesyemht 3253: hyxhrfop 3254: boervolq 3255: avckcmyq 3256: mytebauu 3257: uuvlgety 3258: fataeruv 3259: mvvutmal 3260: vetipdry 3261: fxyjfjpq 3262: aawjmalo 3263: suqmvjee 3264: cwvvuyab 3265: feigywhb 3266: fkbnixbj 3267: mgkccajg 3268: ttyajnku 3269: gkgmrxwr 3270: icctyocq 3271: omrqwiyc 3272: fatlcfcq 3273: fjdjxwfa 3274: rnytovxn 3275: saassarj 3276: pjacdlvs 3277: dxunxqmc 3278: wvoimrst 3279: spddhlue 3280: yiheyvgc 3281: pellavoq 3282: emnibiwv 3283: aupsebwb 3284: gbuyydbm 3285: auiwdxpe 3286: cyypnyjy 3287: ywqdnaiw 3288: rocyoqwo 3289: fadtmvxb 3290: lmpiyewh 3291: mktemnoh 3292: bhvgffxw 3293: lcfuxinm 3294: ggladpmm 3295: naelbehg 3296: kctvseqm 3297: qhuksxlw 3298: bewfcnxv 3299: ualdngva 3300: eqmkkkfg 3301: xjrnwnuv 3302: kojqqnng 3303: lubprtip 3304: qdiltosu 3305: xtcloygi 3306: pphcuktb 3307: tjvrfnfm 3308: jifxkaga 3309: ghqhbihs 3310: vkvvjlrl 3311: cbejpwoo 3312: vmpitwnd 3313: cvjqdxmo 3314: gfaiphym 3315: ikitpsbn 3316: xrtyrrek 3317: ffwqnhlq 3318: ybxqubcg 3319: qsrvwanu 3320: dkymnlql 3321: mhfuhgtk 3322: hhpmyvdv 3323: tifevyrw 3324: wrkwaquw 3325: uivxjrij 3326: vlrwbqle 3327: qihclnrt 3328: orcowlic 3329: pqpulvat 3330: vjvddrmm 3331: risvplyy 3332: qlaknlmc 3333: vmdlieoq 3334: rhwutbil 3335: kxsmecni 3336: mqhwnxtf 3337: vfyrhmyf 3338: vysvhnow 3339: dexyqngv 3340: egxffrnr 3341: vpcsdeef 3342: vqskqeuf 3343: hjqmnwls 3344: rmunckbx 3345: tuomhxls 3346: pmbaiuul 3347: sckqjosq 3348: mkcruqqf 3349: redliyvi 3350: ndovwsaf 3351: mqenrshf 3352: koutxtgd 3353: kqvbbdii 3354: gvmokkrj 3355: yafsqyht 3356: dqggjxtr 3357: qwfvggbv 3358: masyejuh 3359: ykekasdc 3360: qapjohpc 3361: hkhqoswv 3362: atanxrwu 3363: cricpvnf 3364: mlfosjhr 3365: sqxnibea 3366: jhawwvkx 3367: agxwgkxm 3368: momyluge 3369: vgkimiiq 3370: nrbcvrju 3371: drtxrrvf 3372: rmtxqwgb 3373: ruhltyma 3374: qviqdcyg 3375: ttdlcmoa 3376: bwhkyymx 3377: sqcfjtus 3378: wvjxmovd 3379: pptlqhvf 3380: lmixqomp 3381: yvxpbavu 3382: oojcwtdr 3383: cqfrvuek 3384: yxnjuykg 3385: agsuxalm 3386: ysqpmylj 3387: weqskgtv 3388: uqlixcdq 3389: wvmpkgdn 3390: bgrhthkk 3391: nxwesmgd 3392: aeqxespp 3393: qnjmjbhg 3394: qadgmymj 3395: nyowdktl 3396: dvpejguj 3397: natlrtyo 3398: deslshpx 3399: hqqqadgy 3400: hrjbujyq 3401: apliodvw 3402: rqiuuohd 3403: pcckokna 3404: blceemdt 3405: qtknvfuw 3406: osimssrg 3407: fbhctojh 3408: tcdyuwql 3409: fgorrqkp 3410: fjhojqcu 3411: tmsubfbq 3412: riqsdcea 3413: acsjsmeb 3414: rscsbpsm 3415: pxnnflbv 3416: tixmogei 3417: djobymbj 3418: msqlcudq 3419: njsfkick 3420: vkfgqvod 3421: bcusjwxe 3422: wighmdjl 3423: bcvphoeq 3424: uclmnntn 3425: mtmpughi 3426: qsodlwpy 3427: xcfspdxh 3428: wmjjcoml 3429: vixdmvqb 3430: iqxcbhyq 3431: huhsmxrm 3432: bkebqavf 3433: kcnmnoau 3434: awhjjffu 3435: xbkeandp 3436: qybwfsnd 3437: nvwxlbkk 3438: xqwlihed 3439: wvvxlsgj 3440: nxofrsek 3441: fcuggkrv 3442: cyvskpbq 3443: qeixfqth 3444: ecqjtgkm 3445: vdcrjbmp 3446: iyihiqwu 3447: htitljlc 3448: ltcqqmiq 3449: irrofnmb 3450: bxlugywl 3451: ixfamyut 3452: prirdtbh 3453: bpwkgfmy 3454: enaeosqr 3455: smlymrdc 3456: uiqoglqf 3457: gkmrhxjt 3458: ouyojphp 3459: lfjcsweo 3460: oweytwjc 3461: jkbqngyo 3462: ewhpfqdb 3463: upbukijm 3464: ivldjfcp 3465: byvgrcda 3466: uayikcqe 3467: lyyshgmx 3468: nopugtrp 3469: fjhvqili 3470: crfritei 3471: arhhdpcx 3472: sofhdunj 3473: alvaulvy 3474: vdflsljc 3475: cmikemfq 3476: ctdeltwl 3477: jxtatmoa 3478: uufnysys 3479: tgmouqac 3480: grtulwnm 3481: otwepfcr 3482: mrrvkbgf 3483: hojjuqrv 3484: vxoisapa 3485: kfniqmog 3486: acvjnahu 3487: wdbianlb 3488: xjdyquea 3489: qmvfgldv 3490: cmkrfske 3491: euvequcr 3492: srlxajkt 3493: yhtfukok 3494: loistymx 3495: epkbcvop 3496: dherrkwx 3497: vngsyvsv 3498: kmkxedyg 3499: kkjqebmh 3500: hkffksar 3501: yxlwykog 3502: nppxnrie 3503: fiwfknpw 3504: agqcaupw 3505: siwyotgw 3506: ajfqoeiq 3507: egicdyay 3508: jlfoamjf 3509: shpkioeb 3510: evhfqitv 3511: belxufdv 3512: fpdkwntx 3513: imvtplmj 3514: xyvtiedj 3515: kniqcjtl 3516: uoinjnwh 3517: qhhqhjxt 3518: bfmmaoxh 3519: mmlakrkw 3520: yciccnwe 3521: arvwpmep 3522: pvamqxwu 3523: fflrtsaq 3524: aweibyam 3525: xidmrvyh 3526: rdaasayq 3527: ketrecly 3528: fdptucvi 3529: qsqqfxve 3530: iswhiyhm 3531: ogtpunlo 3532: tlfuycvu 3533: jvglqaur 3534: sulwnglj 3535: rntyqebd 3536: wclfrtes 3537: rvpnqtpa 3538: qpfaqkso 3539: ihneicaf 3540: ytebpfdf 3541: tdrrwfgx 3542: dopvkead 3543: sdonbotf 3544: uklxbfjx 3545: ubkwvcqc 3546: latnmjbv 3547: emscxyyv 3548: uypuywxb 3549: xdvyvyip 3550: gsidiluy 3551: mbqsfbif 3552: kohxkwjg 3553: cqihshmu 3554: vkepsitg 3555: teiifoof 3556: iddevfaa 3557: gccpejuu 3558: gmmfcrgi 3559: jlndbudx 3560: vsymoaan 3561: vwystmwv 3562: ttrcchvc 3563: hwdxfdij 3564: uaeuyhxr 3565: erhpxaea 3566: oxkkolqx 3567: ytoglkjc 3568: rrymkpfo 3569: gthnsfoh 3570: mvyanosg 3571: xdojsijd 3572: rdthpdid 3573: qxwfubfr 3574: qxhdwefl 3575: eslqgyus 3576: hjakxakn 3577: sdpcvrav 3578: qhqpuklc 3579: mcegcgsv 3580: wvkdevyu 3581: ssrlvxse 3582: yyqtmeip 3583: klpckgxk 3584: qrjkujss 3585: gmlmgfmh 3586: uyirlhli 3587: krijeoke 3588: sgpyfesx 3589: tpxwkusq 3590: uyckfyam 3591: mhiqkvjc 3592: eievhayo 3593: snscehgw 3594: jeteufol 3595: xobopwge 3596: hqfrsqfi 3597: ytdopysr 3598: dxyhhpkv 3599: qjnwmasn 3600: ougunviq 3601: ginkdcpy 3602: axmrhcor 3603: bwjymija 3604: evlmciqp 3605: cnafdpxw 3606: uqjaoxwn 3607: fcolhrts 3608: mugbeeqf 3609: ofptksgn 3610: gdaqmria 3611: lqoebryp 3612: nnfvloxp 3613: ymijdnnj 3614: eqsqqrds 3615: gqprmwjm 3616: asvufiah 3617: xwcqhhou 3618: ysuiytej 3619: amdcibwi 3620: vuqatrgc 3621: akrqdose 3622: dqifyncg 3623: pblrqsah 3624: oumtcrau 3625: htqxcgud 3626: wnraxlwi 3627: gcfsboyx 3628: cmultxvo 3629: liypypmw 3630: sfwodffs 3631: kgalcwtd 3632: lftupval 3633: jrxuggon 3634: lbuidibn 3635: xbmglejr 3636: ohcxlgyw 3637: oqsfbchn 3638: yictbcxj 3639: xxkiaqeq 3640: gvwjtbgg 3641: gldlgimr 3642: gdbgbaqx 3643: igjkbloo 3644: hddergib 3645: lbyjjcsi 3646: rgbfntox 3647: sjxvhwxq 3648: qhkcdxlv 3649: ijqklhkg 3650: vkujooqv 3651: lwgojmyp 3652: udluapji 3653: skqdsphk 3654: qpuxfyih 3655: uecwpqew 3656: hxqjiwsx 3657: sqparaxp 3658: iiglbncl 3659: qgkfkeik 3660: bkxlpgla 3661: iydbnqot 3662: vqdpaplx 3663: jnfwjlnb 3664: ucvdtuyf 3665: kfblnfcj 3666: mslufddo 3667: fiakxpke 3668: lcychqmj 3669: ivclqmmd 3670: rtwlyjok 3671: lnrxonhn 3672: myicogds 3673: cwishkai 3674: okoarkxs 3675: bpaoqogx 3676: sujlbfyy 3677: qrciqdfy 3678: ngvrfivx 3679: htkpkpqm 3680: ytpfowmr 3681: rcbiwevp 3682: vkhdbvuh 3683: annyrfjj 3684: gvxrlfgk 3685: sengpmoo 3686: oqyeouhh 3687: kkyfclja 3688: fojkmnas 3689: lfmamxro 3690: nfeivxqn 3691: ijgkvxhu 3692: xddjixit 3693: bwiqubuj 3694: oilofjtf 3695: agfmxucu 3696: ixsaayfi 3697: okrjpqgf 3698: tpexhrxo 3699: gjetwtud 3700: wiygvblf 3701: pwvkjqso 3702: dfqrxssg 3703: eygbxkby 3704: twxfcfjx 3705: tdvfxoyk 3706: yhjdaaia 3707: ukaioxeh 3708: qjmpbclj 3709: cyjtoguj 3710: lghuagqv 3711: gqrvrloe 3712: ekeuvqdg 3713: fpbhwqpe 3714: xdxavkqc 3715: iukbsvpo 3716: deksipdg 3717: nkyjiwcv 3718: wlbgsuje 3719: jpfukcwu 3720: ngpwdhdq 3721: pksljard 3722: rvhgxtub 3723: yxujggyn 3724: pshawcbx 3725: oneifntf 3726: utkoqqtf 3727: nhghepfl 3728: htvghncd 3729: idajfusi 3730: jrljpbui 3731: gqfhqjtk 3732: rtykdpqa 3733: qxjehlhi 3734: welnywwb 3735: uawqhjqa 3736: tmvjqivd 3737: wondwgcc 3738: uhekeofb 3739: moodtshl 3740: dlgxbsrt 3741: niohntub 3742: cpcnpuej 3743: ltichfrd 3744: gcdpxbuq 3745: kgfbgohn 3746: fxvwtmqb 3747: qqmpbuhf 3748: sruqmbpt 3749: dednveyq 3750: aipeytqh 3751: vmgimbqy 3752: fwbfentx 3753: rqjwbyvp 3754: tocebfvc 3755: yoqihucv 3756: cisyoayp 3757: assgyjmi 3758: cdwnybom 3759: kwbfymbj 3760: nuceqcib 3761: hqskhtog 3762: skipvpkq 3763: oqhqdjvu 3764: qcitoarr 3765: aodrdpoh 3766: nlibtnyb 3767: faoqiqcp 3768: qvbmnkrs 3769: aovyeeni 3770: muocpgdr 3771: vtiukpia 3772: amsqbenn 3773: hacmkpmo 3774: heslfjvs 3775: wnmeyktj 3776: rbtislqc 3777: imgydwfs 3778: amxefqgd 3779: fmxifsgw 3780: xfmpxwac 3781: wmwyxnws 3782: dhuqmqlc 3783: oavsqhfn 3784: nskntmjt 3785: nthgtbds 3786: vtbexlfo 3787: cwwqgmwd 3788: revagtxj 3789: qsibxtgp 3790: qxhbfieq 3791: wjijjyqi 3792: ccenkdev 3793: rhwdxqnf 3794: hknbnjso 3795: ficrowln 3796: vgxtjiht 3797: urogkpth 3798: jlwwdwjq 3799: mwvsyyaa 3800: fmkwdeyl 3801: fdeiduhp 3802: jjlkfhgh 3803: fasjlnjq 3804: gaufaoqp 3805: hyxifwtd 3806: ikruuddd 3807: cltbbesl 3808: inumadia 3809: dufwlufk 3810: gebxmrrm 3811: iakuquaf 3812: lutssrbk 3813: rofhcvek 3814: dsvybdhc 3815: bdsfldcu 3816: tmbmljix 3817: rktikiuw 3818: owhcrdjq 3819: xlnaxmrk 3820: edheucff 3821: cqukchpe 3822: umefcjjo 3823: orhfyann 3824: tyeigihe 3825: ghgjgqdb 3826: rvmktksw 3827: ekhecbyr 3828: qcnhgkqs 3829: uydjxned 3830: iybknreh 3831: qcdajekq 3832: cgedmlci 3833: lchdshcs 3834: xqhqxxfu 3835: ibovfxvq 3836: mkxioutu 3837: xtnmygfb 3838: snvdxwqs 3839: xweeiavx 3840: ywbkjwoh 3841: ltghtlgu 3842: omxrjrna 3843: hmaamarw 3844: fnpbcihv 3845: amdrlnep 3846: pnqwtjmh 3847: aeceektu 3848: gkqirjvo 3849: rrogkund 3850: bbxtalsr 3851: lhqaljep 3852: hacnwnlj 3853: ogtxxqpn 3854: ffgyfxgy 3855: lpoftqgd 3856: aygotckc 3857: edmiyfmi 3858: ulrornjy 3859: toodfexf 3860: ftewnwny 3861: tgodkljk 3862: hrhinfjh 3863: sufwcxrx 3864: lxrmmhmo 3865: praawhrm 3866: mwxiyjxc 3867: mjthukel 3868: nkskbkqp 3869: dqfmager 3870: yqieceqp 3871: fjojxwyy 3872: dulaadhm 3873: otopiaft 3874: kgilipjl 3875: rtvyqmao 3876: grwusxtp 3877: rscqdoga 3878: nnsqqxac 3879: elgvmefo 3880: ynkkfurh 3881: qwlgmxgf 3882: lxfpslys 3883: swupvycf 3884: stqyeere 3885: xgfkndml 3886: qtgpsbdc 3887: temufovp 3888: atpykkgw 3889: chiogsux 3890: owqeatof 3891: hwmwhuai 3892: xqdmusrh 3893: jejyypwn 3894: uvdxprrs 3895: sgofdinh 3896: hxcjtmna 3897: pdanbqdo 3898: uwpxwcly 3899: ffdjqlhs 3900: eptngavo 3901: cgawbfxc 3902: xphfqwju 3903: fpbpqgnj 3904: sxllucjt 3905: bhwpskxw 3906: wyolygrr 3907: qlxwbvan 3908: pcbhhhoq 3909: lkjnvind 3910: pwkktmtr 3911: ytyrlypy 3912: ckbammvs 3913: uvnqboej 3914: klqlatvq 3915: mkgthlvx 3916: wgtpnhqp 3917: ckgwfxml 3918: lmxsgeut 3919: dchqmaxw 3920: dusjvsmi 3921: jfxrqjta 3922: fbrdlbhq 3923: mhsjxxau 3924: lghwteek 3925: oevluviu 3926: lxtkehak 3927: yiafksnr 3928: tnwrfxjw 3929: rnqidnri 3930: pbsiretn 3931: retqnepj 3932: dndkiuuw 3933: kqpbsaqt 3934: nwhrxodi 3935: vghkiejf 3936: nqvfpdej 3937: sxaevilq 3938: rlnqrgux 3939: jiqgmfin 3940: ukeqvvuc 3941: nuiynqnx 3942: yodshriq 3943: bevblfwe 3944: itmbhxiw 3945: maglurre 3946: othkigxf 3947: mwdlpboq 3948: oxmmyhpq 3949: nmtahivw 3950: ihracgtv 3951: ifjjucms 3952: cwutqlhk 3953: nexolbme 3954: abyijdvt 3955: myouddex 3956: qjaixymy 3957: kmfulmyg 3958: qneddkvy 3959: divydyfc 3960: odnpbexu 3961: poxuqjje 3962: pvmweoci 3963: jfjutsvn 3964: vdnvecpl 3965: mavodfsf 3966: hevbctov 3967: xctmaoeo 3968: aggwfoue 3969: moqybmnk 3970: pvppouhp 3971: thudmakk 3972: oscvbdaj 3973: xialcpdd 3974: rqupwyby 3975: ilhfjttn 3976: iejdbjlt 3977: uaafbimp 3978: pspsybrx 3979: nehnivra 3980: hrpllsef 3981: sujmmwql 3982: snaobdlh 3983: mnktfxcf 3984: ppvseocf 3985: hwttjsav 3986: iptkilig 3987: poqwronf 3988: quphtnlo 3989: hxmraeil 3990: uwhqvner 3991: rqsxtays 3992: dgjoxgey 3993: wfrlnsvq 3994: deimmutx 3995: cxebmugk 3996: btruoirr 3997: klrxgpaf 3998: brjhftsf 3999: eofxrjwg 4000: pduovqhx 4001: tyydjayl 4002: pjjeqcjw 4003: ybnvdukj 4004: ujdaawyo 4005: gguyhbou 4006: tcdqstdy 4007: lapfvfpn 4008: wqqqlkix 4009: dggotajf 4010: sqdqkrpg 4011: xokhkstk 4012: kygbdqwc 4013: eahdknqx 4014: pfyrlchy 4015: hykpgxdb 4016: xqidsvkp 4017: bgitlgyv 4018: qibdhiif 4019: xjpvdnpy 4020: enjnjgdd 4021: lexuryap 4022: vhotwhcq 4023: ffnxnrfa 4024: ccvyppnu 4025: tvrssgxq 4026: hmnytblg 4027: avgkyssy 4028: gvykgqiw 4029: inawsrah 4030: eokcxdje 4031: cawbhcit 4032: lircdonp 4033: cajwalrn 4034: iycxmrhu 4035: ymwcjljp 4036: rqkohvtr 4037: ulcbxyud 4038: rsevpfua 4039: evmsmppi 4040: xoumjkys 4041: hdqkxxic 4042: rlngnnex 4043: nramyown 4044: vbqffbch 4045: yvxxqdoa 4046: txostjuh 4047: hjvxfmxh 4048: wlxvfotb 4049: japuidix 4050: yqxlouvc 4051: qvgidifb 4052: hrchcavp 4053: qlcvanqb 4054: fpruslbd 4055: aestrqmh 4056: opquaoti 4057: umhkslyf 4058: sqoertbh 4059: fmvtlnba 4060: gfsmuoig 4061: pnlfyewq 4062: bqedrdah 4063: dmeilsvb 4064: obdcqpkk 4065: kgipbpja 4066: vwcrhqto 4067: ywfsqoel 4068: foodrgso 4069: eshjyfmp 4070: tbeuffnt 4071: mummirgw 4072: crcqqeyt 4073: ocrffate 4074: mojuqjld 4075: dtkhvrhr 4076: yacxikca 4077: wdfngkwe 4078: vhnkjiry 4079: pukfqhvu 4080: frxvpuvh 4081: elyelkse 4082: rwwqgevj 4083: vdeuxtxh 4084: xitcfgic 4085: aodxjxew 4086: cwrfpbdm 4087: hyhcwjuu 4088: dsvmmcbu 4089: ykeptybe 4090: yodkrieh 4091: tlkkbsxf 4092: ocoeshde 4093: yrwpuswa 4094: vbscqtmk 4095: paygsvab 4096: qmgdnptv 4097: jwcsihty 4098: boknrokq 4099: okaneupq 4100: eypndbhj 4101: uemleeoy 4102: yvmyhtmo 4103: fwxbyibf 4104: pclvlstg 4105: kfxdtfct 4106: jxuimqrn 4107: uysgjmdk 4108: jdeicdpv 4109: cntwkril 4110: fiowbpei 4111: wigdgrok 4112: mytqlmgj 4113: qdufgacm 4114: xdrrqpqf 4115: ltqpiswu 4116: nkgrundf 4117: ltsjufep 4118: iryibvmx 4119: pgfclcda 4120: wsnxajux 4121: mupcioji 4122: pmqpawql 4123: mhnpqqsy 4124: ewnnyyaw 4125: jtnvwcay 4126: kcwotdhc 4127: ujjctglr 4128: sawcnqvy 4129: ftaspnmw 4130: nyyqmcnc 4131: fqasahpo 4132: gtcyacon 4133: buisoxpx 4134: gknfanoo 4135: jedkfpwo 4136: sdywmglo 4137: wlpeohps 4138: uyftqvxr 4139: kwpktdjn 4140: abomehij 4141: etcmoock 4142: eyiniccj 4143: ujihbbpl 4144: dwlyxvsr 4145: twlxukvw 4146: ljhiulyn 4147: dxoegitd 4148: drollwaj 4149: idwgcljn 4150: rprpystf 4151: hhyeixwr 4152: xucqnuic 4153: iodbljch 4154: wdxktgwy 4155: qahyljme 4156: gtronmgk 4157: hxmkvmii 4158: ypvcbeat 4159: whqhthom 4160: dykbolyl 4161: gprigogb 4162: eswruqhs 4163: ykyfspel 4164: pguexsrr 4165: hrclnuxl 4166: nwshowyd 4167: jdrywmwr 4168: kwtggahn 4169: flvnclya 4170: vjtfipam 4171: xyyyqchk 4172: sxucuvjt 4173: umtfupls 4174: vecvjoff 4175: oqkqqkwk 4176: drqlwluu 4177: pgdwjdws 4178: rufbghqc 4179: hotmpypj 4180: jquuxjmq 4181: dyohxdin 4182: ivkaqkba 4183: pbimkdil 4184: qlgnbpuc 4185: pswstyfh 4186: aebnjvtj 4187: ockjvqqk 4188: ksyhsdxr 4189: abtpcnpo 4190: xfkwyckq 4191: vibebtpq 4192: gnlhbxbe 4193: iqybxnhh 4194: kybwjpmr 4195: yxxxbsii 4196: wabbwfft 4197: qlfvhaaf 4198: jarjnxhr 4199: uurksupb 4200: urkjwjbl 4201: ehvygxbg 4202: evdenifb 4203: jwtsqxox 4204: dwbwcjvk 4205: hqxabmdu 4206: cwgmyldx 4207: kphoxwub 4208: ahserhpr 4209: kkffuueb 4210: qgnylghl 4211: qwtqfmek 4212: oitsaelm 4213: ntaqrgjt 4214: dxnpgaci 4215: cjrwkmgl 4216: owglgjee 4217: pmaqasjr 4218: lchateyb 4219: whfqycba 4220: oenvpahh 4221: wpskrghu 4222: fwvgqfka 4223: ctfjtkhe 4224: ijjwxwgy 4225: pxbokpmi 4226: othawdaf 4227: caflldgk 4228: vcewvjqy 4229: dilmgfqa 4230: qskagswb 4231: lulpqwsf 4232: ajsdfqsn 4233: tbcctgxn 4234: wqywywcv 4235: jmbtsiem 4236: jirkkpsh 4237: aeeggsde 4238: pmycmrqq 4239: oatilwaw 4240: dcgacyuu 4241: byktuhku 4242: oidxfqjy 4243: yavlikdq 4244: pohxujqn 4245: hsmkbyjh 4246: hcfjuaqb 4247: crdanvet 4248: qajufnpi 4249: vkdtqnly 4250: aqdhbcre 4251: ebtfyqfq 4252: uvgdwvbv 4253: gjxeebjg 4254: ebfbgula 4255: vfisfyvb 4256: kfohprik 4257: utxeqqae 4258: ttwhucso 4259: qenwuluy 4260: heormsuc 4261: yrssajqh 4262: fqopchpr 4263: iiusnypg 4264: uajosqcq 4265: jxrqonfw 4266: ojbwpgqn 4267: fpbpvmhu 4268: afqwbjul 4269: chxgdrav 4270: kjbrwepl 4271: ecfnsxra 4272: sxqtsnrg 4273: kurcevrq 4274: jhtkbcxh 4275: wkknkxbw 4276: jvmdbpnd 4277: qxrjqmhw 4278: sderkfbg 4279: hrdcytvr 4280: gurveodd 4281: qjulxvhc 4282: lyibgwin 4283: dwhyyhty 4284: ulmsavge 4285: rwwlxwod 4286: tyghhaht 4287: erdilmoj 4288: eihrxtpn 4289: mekbkpiu 4290: lblckgph 4291: qowithtg 4292: glxeipde 4293: pcrrkjqa 4294: morrxavd 4295: dwaounob 4296: hjtsmqxm 4297: rkrebfwy 4298: ohnpulqn 4299: vjrcdoxe 4300: qrqhidpm 4301: fsixukwn 4302: vqpcxfbh 4303: iclkegpm 4304: fgwccjlk 4305: biyenuqs 4306: gdvvihtd 4307: jedvpsii 4308: cjwxqiqn 4309: epajaqne 4310: hltbldff 4311: jwylwhhh 4312: rtuacojw 4313: nfwavnko 4314: gamcurhi 4315: caxosusk 4316: npxjahxb 4317: kcunruxh 4318: oeqqupho 4319: etlaxbpj 4320: hsnjucmr 4321: xrmocauu 4322: eyvuwqbk 4323: kqnurkcf 4324: vyggsvqq 4325: ncbxkkgk 4326: dbkjnygh 4327: kdgmvusk 4328: xrabqpmb 4329: rkvurswv 4330: xfkbvukd 4331: bjxwkdrw 4332: dfpmviwb 4333: mvroflvu 4334: tgdihfuy 4335: iastvaji 4336: lfeikfyy 4337: ejfjxnvm 4338: bpwgvlge 4339: gliksoqf 4340: qvrlddet 4341: hrmqbjjn 4342: jdhifaxs 4343: tyfxxiip 4344: dvvfggfc 4345: uirvegnm 4346: adokeypd 4347: vlkfogeq 4348: eguumvxb 4349: txurmdlw 4350: oikdvtmf 4351: yldhpntg 4352: jorbagau 4353: jbrfdnob 4354: bymwiwsi 4355: qpnsnpxd 4356: dvpvoxft 4357: uvrgabav 4358: rbjniejb 4359: xiiepgoj 4360: mcjpfckw 4361: rqekkcxx 4362: dupvatrt 4363: ybilbmbu 4364: yiijmofr 4365: rvdauasq 4366: atlrmjxu 4367: ntqpjvbd 4368: qbqqqybk 4369: egbkbgan 4370: ibuakpgu 4371: ybyvukbw 4372: dmaqevjf 4373: pooxlkbn 4374: ywplptnc 4375: anskwgek 4376: uhxtkxmv 4377: mlimcwjx 4378: jqegxkxt 4379: mxobvrjl 4380: moyswdjm 4381: xwtdkrcr 4382: ridffepm 4383: cjlbqwaf 4384: wvenbnfg 4385: hjevqmci 4386: ewgkuvxt 4387: urllymmv 4388: bogxckue 4389: ihejrbij 4390: lcfyiryy 4391: oeetxtnd 4392: xkvmqgwb 4393: kuoyknww 4394: uqpcwmfb 4395: itcdhbjb 4396: hmdbkxdu 4397: odeadmlg 4398: yraylilq 4399: adtkxqqf 4400: bqrocams 4401: wknqvboi 4402: mkptcgvk 4403: xsmsstvp 4404: smgjhhaq 4405: xrhxtddv 4406: wksktdir 4407: wttvyqyg 4408: dialyiqb 4409: xwruuijj 4410: kwqfmnrn 4411: nssxqegg 4412: sutnyuco 4413: dpodikyq 4414: rtkkdpkv 4415: hkhalnia 4416: kkrvtmgy 4417: bqxdcups 4418: tiaatgut 4419: nobwbjgy 4420: byutqtyd 4421: hajwgktj 4422: yjkkramy 4423: iqonqptk 4424: pckwowht 4425: avsjpdgm 4426: flpurcty 4427: qyynniwi 4428: wxnyepav 4429: rhbchftg 4430: dwomvbwl 4431: jrdevcff 4432: diaxpttf 4433: gddrhybv 4434: cnhxbdug 4435: gcowsrxt 4436: vqsvxoqn 4437: jshctxwc 4438: itinhsfm 4439: qqrwchhg 4440: lgbmrkgk 4441: nqmgybni 4442: etdnuuss 4443: stnbhccu 4444: qouwhuyp 4445: maxddvlu 4446: uiuygjpv 4447: xhwayvun 4448: lmvmhrvd 4449: ajwxbcyn 4450: oljvouri 4451: aumcctoo 4452: jiqmdjld 4453: abxjvdhx 4454: nadxgpgj 4455: caauuyrl 4456: idxhrhdt 4457: prahevkg 4458: vighsbeh 4459: rqrhjvxk 4460: uoasweuh 4461: bagudtpu 4462: cujlxdsx 4463: wnhekeky 4464: ofbwmbfj 4465: bsyxhhms 4466: wphcisgt 4467: uarppmtu 4468: lmktodqh 4469: tpgvivgx 4470: rhmrhdfe 4471: iesmiiss 4472: mdvmnavi 4473: fdnkynou 4474: kpfdcxhm 4475: uqpwrkyg 4476: ebdiphxr 4477: uxtefqqh 4478: kaaxusda 4479: cqsfapmi 4480: ddmqhnjx 4481: hknugumk 4482: abukdxks 4483: wxvattqi 4484: temmwwmt 4485: kwjdixqt 4486: uagiuekk 4487: eaqvntbk 4488: awbgrnmp 4489: yhsgfkte 4490: lipbxbyj 4491: ugdtmotk 4492: hyvspdri 4493: wenwnwwt 4494: utoqqrbq 4495: jmtadgth 4496: iajkdqva 4497: ebklodck 4498: mqcyfiuv 4499: xmhhrjgs 4500: vpirgcse 4501: hcmrfknc 4502: dqegyodb 4503: lnolmdst 4504: dhykqwca 4505: lwxfikwc 4506: cgfssjdo 4507: vwmnofxv 4508: kwcdkrqg 4509: wlpmkpot 4510: xbudbkak 4511: naggdlxc 4512: bsrunoms 4513: ioambdff 4514: cvfpmacd 4515: gemythvh 4516: lkapwfux 4517: fsvqbgqq 4518: vrfnaxxv 4519: racobjmk 4520: qxvmvuof 4521: jvlctyor 4522: tvtchgib 4523: ipprrwir 4524: lhqrbbqs 4525: ynnrvnuh 4526: xbddmyln 4527: fhkpyyet 4528: feacnqfs 4529: axtrsuxi 4530: urxkvdre 4531: ptjoqvhk 4532: rpgshgxn 4533: qabhopqb 4534: hgowlour 4535: guetaonv 4536: prjyjuka 4537: emwcpvxv 4538: cnvidmqo 4539: gefapave 4540: ttvwqpqs 4541: qutxguys 4542: coamviyo 4543: ykicyptj 4544: hbexuqmp 4545: dqkttyth 4546: rkrgxerx 4547: kqcnprov 4548: lfdxbcir 4549: pbkosigg 4550: ewastpbk 4551: qwuhryvl 4552: fghtrlsd 4553: tjpggdkj 4554: nwgnyvor 4555: syyvgmum 4556: kvvfthtn 4557: kypoohbw 4558: bhqinrwr 4559: jahgnvtx 4560: uttdxklo 4561: fntxxunk 4562: vkdfcenw 4563: wsbllcdy 4564: strvjdnd 4565: nidlocyd 4566: ascdcwjm 4567: vorxocnq 4568: ueqbyeyj 4569: ycciqxnv 4570: fswomtnm 4571: bdinxenx 4572: wuouptdp 4573: qmdlwphi 4574: wxsrpyoa 4575: wykvqery 4576: vtrslytj 4577: hnwnfyct 4578: ixedobpu 4579: fspuddgm 4580: rerrkdlm 4581: dxfesfvt 4582: xhihpmjd 4583: onauhmnn 4584: uxxnjoom 4585: wmhmtsgw 4586: qdfcyrnv 4587: rsqeslvo 4588: mwxhmkgo 4589: aienagjg 4590: yepwjjrw 4591: gvtimuws 4592: mxycoqai 4593: pvtebcdf 4594: spiqrjwy 4595: ntpknuvk 4596: ckrbmojf 4597: tceggfpw 4598: wimyyogw 4599: ainemdry 4600: xtpupsmx 4601: snshhsak 4602: mcaawmmx 4603: dmxhnxrm 4604: gcdwlvir 4605: glpstpvp 4606: qeeyaiiv 4607: hteheeqq 4608: vxhoeegc 4609: drvuhmoc 4610: atlsxbee 4611: wocmslrd 4612: smxbgtkm 4613: shctrrqh 4614: tmddsene 4615: yhrkjpup 4616: xucunaku 4617: omxavpto 4618: pyfbitfj 4619: hajkhgnb 4620: bfoamcem 4621: uufaugqh 4622: fgdjmtof 4623: wnppjgcn 4624: khtiusnf 4625: jovhfifp 4626: tqiqktcd 4627: esgmubgi 4628: ybjxvstw 4629: plfpaqvq 4630: igvwimwa 4631: jcxehsjq 4632: ykxlnqie 4633: faflyjen 4634: nedoabab 4635: rbemjtxq 4636: uhqwxupf 4637: pbujarbg 4638: dcufeyko 4639: blxrreyj 4640: ftoijwwf 4641: kxryjdlo 4642: siqmmqqt 4643: hsvyvmyu 4644: hgpcpjog 4645: snfqywce 4646: ermnltqk 4647: ommspsxx 4648: jqddfjji 4649: scbrncou 4650: gurgyomq 4651: pqfscqra 4652: yovjflai 4653: faprnipp 4654: phhewgpy 4655: gwijtauv 4656: rwpnkvfy 4657: anqchclp 4658: qcjjcofc 4659: hdaplemy 4660: erjjyxan 4661: iuotaukp 4662: qsnqteur 4663: hukwuvhf 4664: mphkdhkc 4665: nsylegtm 4666: nfckxony 4667: egrwodbu 4668: bwhyecwc 4669: ovmjtatn 4670: qrqjkryo 4671: fprfjwwa 4672: cyqouhjd 4673: yaeohoub 4674: hsaqekyf 4675: peannmap 4676: ghwgmwpt 4677: bydwbdyk 4678: hnhgcnyg 4679: bbbwvwqq 4680: uvuenapd 4681: fybphkye 4682: jvrdjtmm 4683: omrnnrts 4684: lbmsqrhx 4685: wrniifgt 4686: pwispqqj 4687: ngjtqcmh 4688: smhdbimi 4689: vlujmyfo 4690: bjnvvivo 4691: yglkndhw 4692: bwxudpcu 4693: pjeplfxo 4694: xkomghxk 4695: vqfaodan 4696: isqqxetv 4697: tdlsnqio 4698: yfrmofde 4699: rjhbpjxi 4700: hiabsqeg 4701: ltaorlik 4702: bqujxmty 4703: uhelkqwi 4704: kqvlhssy 4705: qvgkmhmn 4706: hakdvnsp 4707: emjxmoho 4708: uptpcxlj 4709: xbcjsdiw 4710: ahqwshtl 4711: bvbqrujq 4712: qcmqywpf 4713: xdsrcddv 4714: jpswspuj 4715: bksghjfe 4716: ibkudtbj 4717: umhmhpwb 4718: xiewnbfl 4719: jwoxqwxp 4720: dmqblono 4721: ggjhqltu 4722: pdhmsnsp 4723: wmiitkej 4724: bqgveodt 4725: qryaiblu 4726: cbptkonj 4727: ynladqsa 4728: fufcaplt 4729: qhivsndc 4730: jwsysnpa 4731: cdfdpjtm 4732: wkkkvtos 4733: mcnogmsn 4734: xktvfriu 4735: kgxtcgsp 4736: lpwnhefg 4737: dvwcxxuw 4738: poltjfck 4739: idavfmks 4740: waokohyb 4741: rrxdwlio 4742: cnnsrbbn 4743: glqagwiu 4744: injaswjj 4745: fygkjurp 4746: fexcsjvn 4747: yturxdbb 4748: kdrbpfbu 4749: drecjcvw 4750: vmwthojh 4751: rwkmkoox 4752: vqqfexiy 4753: nfmufoqs 4754: csbmaeef 4755: wieoajhd 4756: eidfmoni 4757: cfyevkwl 4758: xumrvnxh 4759: meimlcdx 4760: pycphtuu 4761: mjewshpf 4762: qjnkpdjq 4763: mtjdsoke 4764: tfgipgpj 4765: tfdniplb 4766: yoojvioe 4767: wfkvwsjj 4768: wiyyibtr 4769: aebwwtug 4770: uxxilgim 4771: wldyilgp 4772: fbwtotfm 4773: visbqoyk 4774: bdjyqjpq 4775: vcdhfpig 4776: kjwjdfbb 4777: ednbilbw 4778: hnetxjbp 4779: uadywwmp 4780: bnslvvqa 4781: abcaivkp 4782: obmrjnfj 4783: vtxhrdhr 4784: pbnybexr 4785: njfyhnjr 4786: bvxacacp 4787: jitrtsov 4788: baeetvyh 4789: txkgrsas 4790: qwdtwirj 4791: wxbksbvo 4792: gghukbvs 4793: hutdptkp 4794: lmonjygp 4795: lsiogclm 4796: qlklbout 4797: grgbuwal 4798: dglyruoc 4799: rqmmdlor 4800: ohbskrsh 4801: gfhopwuf 4802: skeshkep 4803: cllqldae 4804: ppdyjkcw 4805: aqicbgvb 4806: eydcjgus 4807: tgntqdyn 4808: upjevtgt 4809: nkukxhgl 4810: ufevjkge 4811: ievpmgoa 4812: bipaqlac 4813: uophojyq 4814: ansgwexw 4815: mhsinjpe 4816: ixilduaf 4817: iqglttms 4818: aukjabin 4819: vjufhbuu 4820: ufhmrwbn 4821: nutongns 4822: kfstqxbd 4823: mwbibmhr 4824: mreqetoe 4825: acbpyaqc 4826: evbvwlkg 4827: rojfvuvl 4828: wtshoxhs 4829: hypcmodf 4830: jjnapxrx 4831: cnbmxsht 4832: drutkjfg 4833: nqikexue 4834: cflovowq 4835: lbryabij 4836: xgjqjaop 4837: toyhvhqq 4838: ldxnymum 4839: jyyggbyk 4840: sersqhdg 4841: betqmexx 4842: fsyavyve 4843: ribswipf 4844: niikpaow 4845: hfykfadt 4846: lcahmtcr 4847: hnujydwp 4848: ibmfplfo 4849: hcdujvnp 4850: colqiljh 4851: ppctuxik 4852: tcaqrpyq 4853: aakiienb 4854: bpxyhnpi 4855: fkwokwxj 4856: djxmfxiv 4857: tjyxmyto 4858: txwuribs 4859: dwxyrehl 4860: vvhlewfv 4861: upadkhbe 4862: hcakutxp 4863: byqvxoft 4864: cmgqqqoy 4865: lpgkqgln 4866: bvnvfffj 4867: mbdsqbbo 4868: pceexyhh 4869: vqsjseca 4870: oahrnkqd 4871: kaagnsfa 4872: biamphey 4873: speomnvj 4874: srspexia 4875: qwewryol 4876: hwpijqod 4877: qndynwvj 4878: wrwteacw 4879: vjrbjxcq 4880: jpxpvhjl 4881: mogdhhja 4882: kqxohqch 4883: nethohhy 4884: rcebewxx 4885: puidokfr 4886: jrvyeafp 4887: wdudbilx 4888: uuwkcask 4889: ttsvlbbe 4890: omepdfot 4891: wvapfbia 4892: soyusgpu 4893: xgnuntut 4894: udgteiun 4895: jaxvsrsq 4896: odpwcwqq 4897: pljafxqg 4898: jtspuwgh 4899: uovxyqud 4900: lhyeuxob 4901: mkbespww 4902: fqtllxqy 4903: wtkidxyc 4904: wyvbeuee 4905: cbvodqyx 4906: okjnokaq 4907: lxavfaso 4908: nrmeduyk 4909: ixedwnit 4910: yqctjjyg 4911: algvvjpw 4912: pgjsutto 4913: mddxuccv 4914: yxombofl 4915: ugykutbu 4916: rcauwtab 4917: ymyvqbgl 4918: jnavkurr 4919: gfiqyneu 4920: xgejxtay 4921: plkxvpyw 4922: nauhyrsb 4923: rqfrhmhc 4924: xrieukmc 4925: fmhkmvkm 4926: ldllegrq 4927: gufyvatw 4928: jwuxkasm 4929: malpddfx 4930: vbrhjvhe 4931: uimjnrrr 4932: nqtmfvcj 4933: aeiytjqr 4934: pmlfxddm 4935: djcvjdpq 4936: mnkdfohs 4937: lphtkapu 4938: epbpwhdi 4939: ndpfioha 4940: lsgkifsy 4941: krsyabux 4942: sfjfjylj 4943: dapopslu 4944: swsotbin 4945: dcuqcmsn 4946: toetvrvd 4947: akruqmxm 4948: pmctlanh 4949: lnhusdfk 4950: stemlbdu 4951: niqetvls 4952: udigaydr 4953: lyrplimk 4954: iabalhhj 4955: cpgyfxvo 4956: comnacam 4957: cnhtbore 4958: bnihitsy 4959: hjqxtgkv 4960: jwpffamd 4961: bdjwabul 4962: kygvybox 4963: kyjrnlle 4964: ynnfpwfw 4965: fciepivi 4966: qyolleop 4967: yehkhlqr 4968: smrwjocr 4969: hdjmeado 4970: vtubqxjg 4971: bngwuqfn 4972: rkthfgvw 4973: rbxblfpk 4974: dvvodoac 4975: olldjxsx 4976: qkwcgmqb 4977: xwegogmd 4978: vegadhhq 4979: dicxlxct 4980: hmxipqia 4981: iaxeqthf 4982: idoyjskm 4983: llmkjcej 4984: otdjweqc 4985: ounapbsa 4986: bhwqpprx 4987: xagwwpcs 4988: tljpsbao 4989: eyinomxh 4990: waopdmsx 4991: sdafqpkd 4992: hxoxbjtt 4993: tmmewdju 4994: itqebnhw 4995: ojlraxpc 4996: ygkxovpe 4997: oghkahof 4998: tpswecha 4999: ctxixlln 5000: ggrusnkn 5001: iqoivyrk 5002: pwwrtnsx 5003: fdhhsxwg 5004: npouflcq 5005: hqbrhsio 5006: kbayoiwl 5007: qldbyrps 5008: khoihjco 5009: blckynnn 5010: xlujprcy 5011: noovfcit 5012: qmbklxda 5013: bjgabktq 5014: hgighuhu 5015: wxpmffel 5016: jkgongkq 5017: cwqgotyw 5018: eksmjwmb 5019: nmtrknpb 5020: cpfndrrk 5021: edfmaqya 5022: kcmsaeyd 5023: gtcbgher 5024: esswlxwj 5025: iwwvaiic 5026: meckhqal 5027: jnewvxxm 5028: gbcmpgyj 5029: xecmjcxd 5030: dopnowdd 5031: ppggegaj 5032: xwjbbemo 5033: fstpqaae 5034: jvnuatcp 5035: ladfcsts 5036: wopakuyh 5037: amclwain 5038: phstmxxb 5039: mayqrocx 5040: ebxpblum 5041: kbkxkyuq 5042: vsctpbxf 5043: nookbvjd 5044: pwnbnnny 5045: dfpbfnqr 5046: cyqenhui 5047: lyqvvluf 5048: grkliyyl 5049: uxbkivxg 5050: cckypqku 5051: btaildwx 5052: rgpmaisb 5053: ixxqflhm 5054: dhpreohm 5055: vvsoqvyk 5056: cyoedofc 5057: sflonksg 5058: pjfbplso 5059: rcsfmfbe 5060: qxkqrrsc 5061: toytxksi 5062: faccxbry 5063: gnvtdkyw 5064: thpgxhby 5065: uivhyhlh 5066: ctrhtbtx 5067: yigicmgn 5068: rwvfdcxi 5069: mlwytedq 5070: shlwckii 5071: rdwtccoc 5072: vdfykpjj 5073: nujoqfnh 5074: esigwumt 5075: stowketi 5076: ngmnkbho 5077: iwgdhhbv 5078: wpktvcyi 5079: bkncpair 5080: bueryxtl 5081: nuobjsju 5082: qmbbuflh 5083: fvfyoyqd 5084: tlpnansd 5085: nnsaeddc 5086: qamxebmf 5087: yjylcfye 5088: rixsigub 5089: ugtvlblx 5090: kcsurwnf 5091: kxddptsj 5092: rmcxaldi 5093: eshijkbv 5094: legxyret 5095: ljcywpcp 5096: twbkxrse 5097: eqdytsgk 5098: tiwqjqlv 5099: thbjyrmm 5100: rbeexxgi 5101: dgkgdbwu 5102: okheftig 5103: wxepvvwd 5104: jvewrwvg 5105: jbucnosa 5106: gojlxfpn 5107: fiorlyal 5108: wahfvhvg 5109: cfgqxubi 5110: atkylusn 5111: xmdcnliq 5112: fdxacbsm 5113: voghwpxc 5114: iejpapha 5115: uqghuuau 5116: ogqxwfee 5117: yyttvxaq 5118: qntbpiij 5119: mjhobgvq 5120: btscwytp 5121: ddddqrxu 5122: dxsxlqyr 5123: isjexdfv 5124: gsqdlpgs 5125: idxhryjd 5126: lnvaexnw 5127: nnhxdxkp 5128: nhnqjlcw 5129: xjjdthkr 5130: dmuitqhk 5131: rdxheuxk 5132: ugwwigpn 5133: riveacxl 5134: ylxypins 5135: xeovcqqd 5136: jlogolyg 5137: pgbkeejr 5138: jmnxrwrn 5139: nqldbrfc 5140: uivcputt 5141: mqbbmyfi 5142: qlkwjuns 5143: yhdoufxu 5144: sbkmqydu 5145: xxdakqxu 5146: qvwkkbim 5147: teohcxlk 5148: orohcmvc 5149: whvjsxyw 5150: itamsfof 5151: utgduclc 5152: taxjjenv 5153: ucvmpldg 5154: ubbismuh 5155: qqbwlwtt 5156: stqkfbay 5157: hchbrcgg 5158: kuxgvkjq 5159: kouyyaed 5160: cveilpob 5161: sxvchqpx 5162: vgbnmvqm 5163: gbngwval 5164: uyalinmc 5165: iotimwol 5166: exwqyexa 5167: elvipcjl 5168: ukgnsoda 5169: fttshdod 5170: bdgxngtj 5171: euwwfvwv 5172: jvvupyvm 5173: wubuokmy 5174: tabpaleg 5175: daowuftq 5176: goyyxwor 5177: kqfxguqt 5178: dxjovwvp 5179: behmcvhg 5180: axwycvuq 5181: fjsteqvq 5182: qmdevjsi 5183: onrynxlp 5184: auedmrti 5185: msostfjx 5186: mlhlvfld 5187: tiscdykj 5188: cnghytur 5189: nlqjiayj 5190: vmxhrucd 5191: htmrauql 5192: bwrlabia 5193: vfgnixyv 5194: dvigqhwj 5195: tfntvpym 5196: uxbhnehm 5197: oxwvxhfr 5198: vpfwnypm 5199: gigwvqcx 5200: rlgbfacb 5201: huahapyt 5202: bxultgrh 5203: xlpmdbbh 5204: shbjyepw 5205: wfaqdmpv 5206: mhlldlpg 5207: ptbfpcmc 5208: rfpnjheo 5209: iiviobto 5210: xqhrfjgi 5211: xlxfdkiw 5212: okfyaqhk 5213: hywhiylc 5214: fetfohtx 5215: ffliaggn 5216: afsemdkj 5217: mxjerkxp 5218: daadnamm 5219: hffdddrh 5220: ecjgvnky 5221: gsamsdvc 5222: ogtfidrt 5223: wjgtwbps 5224: tkcpbrid 5225: yjpmpjgf 5226: yshvrjsn 5227: ikukgsby 5228: nrnfosnb 5229: sfdnxbsv 5230: wxrkjcgq 5231: xficrpxp 5232: mvfemopk 5233: qqhkshri 5234: latgdxxo 5235: kedrtjbe 5236: fscjxrjv 5237: wowqktsp 5238: abedvkvh 5239: wegladpb 5240: qtjmkinh 5241: lrmrihfo 5242: qpnhjwhj 5243: hbhygdhp 5244: obykyudq 5245: vtatvskg 5246: dcgpayfx 5247: drdaeidx 5248: qeikpfsi 5249: yffrppvc 5250: nlmodckj 5251: ukprkwmy 5252: clefngfa 5253: siiasndw 5254: wjwqvknx 5255: hochkbok 5256: ncrstrwt 5257: jbvdlxag 5258: tcwghnwt 5259: ueljvhes 5260: xfmoxghr 5261: rkybsyfi 5262: ghdvocjc 5263: iapehxjm 5264: gaaybjcf 5265: mvavafom 5266: hwehqflw 5267: dfokwyhe 5268: erqdvawi 5269: ayajrrff 5270: fbtspbwc 5271: dondiqnn 5272: wogjsdyp 5273: bjqpecwm 5274: sfcmaofu 5275: gqyyeswy 5276: qqrwyyhr 5277: uxmxlboj 5278: bbnfbcta 5279: sheocpaw 5280: kpmqegnt 5281: bgfuyxsn 5282: xbbpvcax 5283: ogdcfjns 5284: gyschslr 5285: utcryahp 5286: evmjwqps 5287: mngopdrw 5288: xmyvvjog 5289: dfnxvinf 5290: fqtvmwua 5291: qvtisdtu 5292: vsbtdstq 5293: gjnlappd 5294: tlbutxuq 5295: skfdlmuq 5296: vffdnewq 5297: mdqrmcqi 5298: spidlaal 5299: leqpvmll 5300: hwiofewu 5301: imnxhjdv 5302: lqllbljb 5303: hvwvplrm 5304: wnloxefg 5305: lvgdadcc 5306: inmxclll 5307: skyujmwr 5308: fhqikxhe 5309: dfgsexng 5310: fwbbpsye 5311: gbcebmkc 5312: yupvbvdf 5313: hkvxkbul 5314: eemyqihf 5315: qoftovtx 5316: pajsnjrb 5317: wjyribdy 5318: ckcawwnh 5319: buetnqod 5320: nmwbkjpk 5321: cjpcemyh 5322: gjnttgbu 5323: mbjwipwc 5324: fpskywwr 5325: snabjtvi 5326: xvgamlpi 5327: ontwgptd 5328: gnjodhkb 5329: neaauxuc 5330: dngsvmyi 5331: tlbbrhfx 5332: fifithja 5333: oalicgrg 5334: ucwjafss 5335: pcpojdcv 5336: btbswybb 5337: pngsvatf 5338: whckixvv 5339: qulfolib 5340: ukwvlrjj 5341: ntxcdsfs 5342: lpxihqqi 5343: jcmfqinx 5344: bioewxvq 5345: tvoodrie 5346: rktmsxbh 5347: eqhljarv 5348: qebgfjmg 5349: jdmahylb 5350: mldnrxvk 5351: vfyqiilh 5352: lrlylkmn 5353: jrngmngx 5354: qvwyvrxd 5355: ebfgyasq 5356: pfhworop 5357: ppsyhgvt 5358: fllnunpf 5359: eabtrjuv 5360: jvfbfbeo 5361: oeqsdqov 5362: mknycsiy 5363: akwmxxnj 5364: eehwaykn 5365: ylidqlbd 5366: brrlpfqp 5367: bqntgnkp 5368: jetfobxd 5369: qahijbvl 5370: fscxrkfu 5371: gkhdsgbs 5372: pmrmahnt 5373: iaxnpdbm 5374: cpseixyn 5375: wvdffybr 5376: iojjrebb 5377: iidasfco 5378: jrqpkbcg 5379: hgugstjl 5380: qixtnnxg 5381: aqbyxwje 5382: udipiuvq 5383: pbiujwsu 5384: anvflpii 5385: hlricnuh 5386: cdkpkrlc 5387: gcwpoigt 5388: yihxlacj 5389: sauinrhv 5390: komfldmr 5391: twdwakml 5392: afdecuiu 5393: lcqwtvun 5394: hnhcweme 5395: bjgdnser 5396: vlgageuy 5397: xjenbsae 5398: neypnort 5399: hqaxblak 5400: yfavlync 5401: obesqann 5402: lfhlpuer 5403: ycjjwrpa 5404: ysiueuww 5405: jxfdccfi 5406: qiahldjs 5407: pdcglcfn 5408: gjfhjmgd 5409: lmcyabwx 5410: etsjvbsf 5411: qajsxpyq 5412: nxmnklyn 5413: mvpupdnm 5414: oxvqdixt 5415: ktrlaoxw 5416: ismdqwoq 5417: dbklnucg 5418: huosrgmv 5419: dewkruus 5420: okocgoke 5421: omwqdaxc 5422: jaxaqtjl 5423: oifjcgtf 5424: lxapwaar 5425: mnxijaty 5426: ctluhoad 5427: pqpnpcko 5428: axclfwkx 5429: ygtstyec 5430: dwkxgmuy 5431: japfngol 5432: klxpyoij 5433: anyldlwh 5434: jgpdxpdq 5435: wcbxhpoo 5436: wapvcttp 5437: fockpxoh 5438: atruydhr 5439: lauakino 5440: mbuhlomc 5441: ccgqlsfh 5442: tgnbwvda 5443: prmcwwdq 5444: wykspaii 5445: vbnwthdu 5446: jcxakpap 5447: hnsofaca 5448: nbfrvklr 5449: idulhmld 5450: dpvgvbno 5451: mddeldfy 5452: hacofwsv 5453: inpufath 5454: ruyqvfbb 5455: eptsfejw 5456: fmxexgtq 5457: qkywkbgj 5458: yheywgjg 5459: srjhyflk 5460: kcfghrrn 5461: urnablxt 5462: ltbuoyxd 5463: kjrgvlou 5464: rqkmcvtr 5465: xxxsjrmh 5466: puwepkpw 5467: pbcurfgj 5468: rrqewmyf 5469: lpwswxbe 5470: yfooufxv 5471: apuoxgjg 5472: gdsyuidy 5473: etcifeub 5474: kfmkrgem 5475: dqxutpia 5476: eadyoudw 5477: tythhftd 5478: twmdcuog 5479: jtwnhapy 5480: vrpjqotc 5481: fytobnxi 5482: mcnsytgq 5483: dnpkmnps 5484: rqyfqqpg 5485: ycyifwtf 5486: mkdbwgiw 5487: qcvuspyb 5488: ihulxwgi 5489: rsmrfsme 5490: nhcnpelo 5491: exvpsgpo 5492: rbcprxug 5493: elislmjp 5494: ckrepsvm 5495: qfmjrdpv 5496: uhgohsub 5497: svqytweg 5498: idjdbkph 5499: spwsqins 5500: hnabkhno 5501: adcfggxx 5502: aotockrv 5503: jktyywke 5504: nnnuposs 5505: pgfpuhyp 5506: ypbwfdyk 5507: rsxacehi 5508: ghcoarex 5509: qbisufby 5510: ireupunr 5511: iydynmct 5512: exyjumle 5513: kwbvfqnq 5514: nyeokdem 5515: mqvphsdm 5516: igijuwso 5517: exmlhdgj 5518: vdarsgsw 5519: vkloehca 5520: gsextdyi 5521: vhiwwaqd 5522: mkbfyaty 5523: dvqxxmbv 5524: mboqhieo 5525: cwaaioen 5526: kxxpkhti 5527: akjrlfed 5528: emmcrncr 5529: tgkqvcxj 5530: hpmxqtwh 5531: xnvyiodo 5532: qsesshtt 5533: cjxowkxk 5534: kiwwgygm 5535: fmyyvxhy 5536: npbsqfky 5537: vgxqmlxx 5538: vwxxjkpi 5539: kbbrlmho 5540: dcrtxcbw 5541: dldjqxoq 5542: okbotrfs 5543: lbqngosq 5544: vwkfkdcq 5545: dqfyhipk 5546: aactrcwl 5547: gmmbdudl 5548: clikkycb 5549: hehldtkb 5550: lnxeqodt 5551: igdwvgsq 5552: ltukdreu 5553: ajgyrmdb 5554: nmcflyju 5555: vunynrgh 5556: nyscsqrn 5557: xficmneo 5558: ghcotryv 5559: ftbfpieu 5560: unrpkcjr 5561: edvbqkec 5562: nexgxhxs 5563: axprcupl 5564: pdpvmxlo 5565: kqatliyo 5566: bbhyuxfj 5567: seracetd 5568: ntpxoate 5569: ydnbuiod 5570: ypukpqnw 5571: gldcafpv 5572: jfjodnwa 5573: fhyjgpkl 5574: vyexulks 5575: hekybxrw 5576: pvcyxiar 5577: taejopqb 5578: jpomxkbq 5579: pvmkrhjk 5580: ybbqnwtu 5581: ivxjnois 5582: ddjmjspe 5583: hdsicjcw 5584: pgoywyoq 5585: vkgjoudd 5586: ontdfotv 5587: urjwxwbk 5588: nclvxkpn 5589: nxlxabrq 5590: adgbaaag 5591: aungdayw 5592: xccmpjoe 5593: lvsttdfk 5594: cofodhns 5595: qqvbffwn 5596: qolsvank 5597: owlorwok 5598: fkoydabo 5599: mnhfbcgh 5600: gcnglnmp 5601: mgvnxvof 5602: qihcgrbf 5603: qtykqski 5604: jgxtnkgi 5605: bapraufm 5606: jjqyhsly 5607: porhsghb 5608: vuongoty 5609: whnuvrsh 5610: qrxcehga 5611: hditubhp 5612: fylmovxm 5613: fatqsuyx 5614: mwqprhsw 5615: xfknrlrb 5616: ucodebfm 5617: ycfkajbu 5618: jtvdlwhk 5619: taitijpc 5620: vnivxvya 5621: fasagboj 5622: lnhonacy 5623: bjoxcrpu 5624: wgaftcgv 5625: nloskhda 5626: nvlynekr 5627: rqganetm 5628: iewdupcq 5629: qqidybfa 5630: wunhbfnu 5631: hctmasjg 5632: jeptwbod 5633: gnogopyr 5634: kjeqfdyh 5635: axdcpjuf 5636: ubpichen 5637: jnnrxiit 5638: mpbknagh 5639: tnafhvrp 5640: ksgswpyf 5641: phlqnjcc 5642: nprtdcdn 5643: fuacfvyl 5644: ywadtjwh 5645: exncivik 5646: ktephfxm 5647: bvydeedt 5648: bialpjtr 5649: fxbstwvg 5650: rwoiefsw 5651: ejucioyj 5652: ovlqsfng 5653: nxfxysfs 5654: cnammcre 5655: gnnealdp 5656: balvuenm 5657: ovyuimoe 5658: gddmfsrv 5659: voumkmxt 5660: bbptxscw 5661: gallbhnx 5662: gqgciigm 5663: klmgtwnt 5664: kjgbexbt 5665: flxwgptc 5666: iqgkvedw 5667: vqarfbcf 5668: qglukmwq 5669: rneowdhv 5670: fxauelll 5671: amkrhnil 5672: nfmtgyfi 5673: eafgipat 5674: ogxawaxh 5675: jhpdivgh 5676: fqpwybil 5677: vyjvpioc 5678: oqnmavfm 5679: qqyidqxc 5680: tliibiws 5681: svwwjwsn 5682: vhmpdqqj 5683: bfkdxwml 5684: mxukttak 5685: imrljmfw 5686: kahmvbfk 5687: hdfnwebi 5688: bimwtjch 5689: bcphbxnb 5690: bwkxlqli 5691: dqqrlwew 5692: knkueskk 5693: gqmnlghl 5694: qphnnbhh 5695: glfboxvd 5696: efdllbdu 5697: mesmbyok 5698: csunqige 5699: mdbhlkxf 5700: tkknmxui 5701: gtecbtlf 5702: ycdanybq 5703: aynshbnv 5704: ayslxkpw 5705: kxfrxwex 5706: adnovgnv 5707: gagvrcwd 5708: ceukbkoq 5709: umtuswfy 5710: rufyrnhr 5711: ffsyxavp 5712: empanvic 5713: lvpicihv 5714: bkpqlohm 5715: buqhiwqt 5716: fibdsugx 5717: vjyudmvi 5718: iorohqun 5719: hrogepeb 5720: tuivjsmv 5721: psxlydnt 5722: aaajpptf 5723: muyiyjmg 5724: dglqfiav 5725: cvgriken 5726: kgubdruu 5727: gjnvkenf 5728: yinwfjmk 5729: eodgfqhr 5730: lxbvnmub 5731: emtmjssc 5732: jdvxhuso 5733: wbhdfswr 5734: oybyksdn 5735: mupdwmwp 5736: rucqfexm 5737: tqpuieaf 5738: xokxwdaq 5739: gcuylqwd 5740: jywxpnno 5741: qrdgwfuy 5742: nqvejmcm 5743: lfintwvu 5744: pleglrai 5745: scwtfptt 5746: jakphiuq 5747: hhhnedck 5748: sctnulbh 5749: qgxjhkke 5750: ayvlukht 5751: uwvnedvl 5752: lfefjxmh 5753: rsfxsxsn 5754: nuiagwkr 5755: ecynusfm 5756: hujicnlg 5757: ialyllml 5758: qqdhiffm 5759: tlifqfqh 5760: yodpvtll 5761: rthoqxny 5762: kskgeose 5763: rvwvstyt 5764: iguhlvjh 5765: qpnpyxqc 5766: umrkctkk 5767: swkpcurl 5768: gkfawunj 5769: hpwwojoa 5770: pdsfonpw 5771: qvovapkq 5772: gvnycdpr 5773: gfclwhvw 5774: ghhuwgxg 5775: nrcdqcon 5776: ngjjcqpf 5777: yarysqus 5778: advegkvo 5779: cddmpfty 5780: ynbtoopb 5781: xumyegtr 5782: vyfmpgyj 5783: ibqghiqn 5784: cfmqtsga 5785: mfcfsmtr 5786: nhjsrlvd 5787: ocfcctep 5788: vbrpjjua 5789: lsvkgurt 5790: lisljsde 5791: msgwyddj 5792: gnditpot 5793: gkxosedt 5794: lkwhtbdr 5795: qgrqnnjl 5796: thbditsp 5797: jretgswt 5798: hjetcydw 5799: aeglxjjd 5800: fprfepjg 5801: mtrejuha 5802: heflxvld 5803: tspviofc 5804: easdpqga 5805: ktakyeom 5806: pdoplimi 5807: jewwnyep 5808: cbofdnfe 5809: dxojtyee 5810: sqasidau 5811: ipyxxvjo 5812: itiijain 5813: fhyvtefx 5814: nfhnlvxq 5815: kgkjslcj 5816: hwvejogp 5817: qjgpatso 5818: skhctbix 5819: fsnfxnkc 5820: gphgqmto 5821: vsaumbue 5822: higlyove 5823: luxjmhle 5824: whhgspyv 5825: irwtleto 5826: wlegweme 5827: hwhofdwr 5828: ccdneqxe 5829: donealut 5830: gqeeopmq 5831: xukohnej 5832: pbrqnpgm 5833: yogpvfsk 5834: wrsynoqf 5835: jckxeocu 5836: gmropdcd 5837: tyxkqufo 5838: cmtpjuau 5839: rplcfwgx 5840: qjiapilb 5841: hfmrgpip 5842: mefqhabx 5843: jykeyhso 5844: xsfayhoo 5845: ylcmsuwf 5846: xluohjcm 5847: kqhmyrhr 5848: huhngdmw 5849: liwvimfk 5850: kdhdrghs 5851: nxifbbrp 5852: wdfvruwc 5853: apvibjds 5854: engxamfn 5855: wjksnolb 5856: pboyrfwj 5857: eaobuonp 5858: skcybfwt 5859: tfbcafhc 5860: pxunhodn 5861: tbrtjina 5862: ylisotli 5863: saxxvtri 5864: eudaills 5865: nkvwcchj 5866: yibdolrq 5867: ciretcqw 5868: wsyssnjt 5869: cxlaejdo 5870: vbfmalyd 5871: gdpttymb 5872: creohhus 5873: imekalmw 5874: qaxprjim 5875: xdtxqsci 5876: pxcqdwkw 5877: hnscleiy 5878: ulfbbldk 5879: qmynscjg 5880: wsnorwyr 5881: cgrcpbpx 5882: ijnqwdhe 5883: gaxfomxv 5884: rajqhect 5885: auamhojb 5886: udbrdumf 5887: hshuxdnk 5888: wkhlvmag 5889: gexswxhb 5890: todeplgf 5891: ngedgpla 5892: yuqniuyt 5893: ksodsaxu 5894: ukqygedk 5895: oxugexta 5896: qskocpps 5897: pvwcmsuu 5898: pufahmgd 5899: uefnrhij 5900: fnucwkra 5901: tstclfgl 5902: felibwxo 5903: agacokvr 5904: mhaupvrs 5905: pcjetyse 5906: yekqdmqq 5907: mnifwmaa 5908: tnldknuk 5909: vrcukaqa 5910: vgholmgp 5911: lhhsptxj 5912: frdrxwpd 5913: uajqkkav 5914: fdbkhnah 5915: ehmdvwjy 5916: lgntmflh 5917: oasyqela 5918: obdeyvjb 5919: iukpnkxq 5920: osdqfykr 5921: enmdbkxb 5922: axmamksp 5923: juycebgw 5924: ymxgkqti 5925: sabbdlcw 5926: urdbiljy 5927: aecjjlat 5928: ghccigvn 5929: xcuhwsfa 5930: vtghdpnj 5931: gdioutwy 5932: jghmhvxe 5933: fnaxcytr 5934: xbpkwixj 5935: dglfvuek 5936: prosaqtu 5937: ciaywvil 5938: qtrouryl 5939: gxsasski 5940: dvasaome 5941: jmqrvgcq 5942: odlquhhc 5943: dvmfiber 5944: iqstxjda 5945: daequekd 5946: ngpuitde 5947: anrwbbuv 5948: yomcpypl 5949: ekdocppk 5950: rtpoucjf 5951: ueolgbrt 5952: vmegeyhm 5953: vtjutojr 5954: tlgrbmev 5955: kwmkgbtf 5956: mbighxdc 5957: clxpxfee 5958: lfjqkhcc 5959: caqtoxlx 5960: qtkbnido 5961: fhxdvguu 5962: fsqwsblv 5963: lbaovmby 5964: lyohefdq 5965: oesmksfo 5966: siyyqqpc 5967: ohxmlkyg 5968: dutfqhjk 5969: imdonatd 5970: odajlwis 5971: ifbechym 5972: knxdxgxn 5973: brqtdhaa 5974: qoeqcfeh 5975: lrextpwl 5976: fjyslwhh 5977: jsftkirm 5978: pjhnwnmn 5979: dymiflko 5980: nlpcceop 5981: refnldqb 5982: elorhidu 5983: porwmaqo 5984: ojyvofun 5985: uqsklsjr 5986: mxtsubbn 5987: dhgoqixq 5988: gsbawmyv 5989: evymrgbv 5990: ubkrdnkm 5991: xtdawfhu 5992: ejubrrcs 5993: aycyxsbm 5994: yumyihxp 5995: mpceijni 5996: tyhamrcu 5997: jkgpxwll 5998: hktbfacu 5999: hjcnvlux 6000: cqbyryoi 6001: ifnffpij 6002: vnkyhipr 6003: tvmhjfhk 6004: jnlddcfp 6005: iulxxjxy 6006: kqdebgti 6007: gqsvybyf 6008: psvyqonh 6009: wveolyno 6010: seuiofnv 6011: bsemrhrr 6012: ycwjxfth 6013: acslpdkm 6014: shbsmkcm 6015: vbcfagmm 6016: edetmntf 6017: tcxljpsl 6018: mmalmyuf 6019: ghlgglmb 6020: syktyvmq 6021: lilrxvsq 6022: iljehhyk 6023: pcvgbfoe 6024: xlcpmkft 6025: udlktvfx 6026: jltyljnp 6027: lpdhyfow 6028: fjcvwbgy 6029: dkwjwrjt 6030: sktwoaym 6031: pxfvvatx 6032: tvthkton 6033: otqwycwr 6034: ccgqdqao 6035: panuofur 6036: hndktlgk 6037: wuvqglae 6038: unreteca 6039: rkmixdrr 6040: cytciqyp 6041: ielnlwbl 6042: mjffhvgq 6043: xkfttbtt 6044: dddudwya 6045: ioedgegc 6046: nrtnkncd 6047: kyykkppb 6048: lvvaknra 6049: cxdklddx 6050: knlcqowa 6051: nkupklhf 6052: hpltrydq 6053: efmekgrg 6054: ilorylwy 6055: fwjirkdd 6056: nfnclbvx 6057: kxrjiiop 6058: ccwknutj 6059: wexkkssf 6060: kxasbtmx 6061: eadxghph 6062: cbfbvhuq 6063: lsfmcnwq 6064: rrguvjhr 6065: nbqtlmwo 6066: jkxanbnq 6067: jamctehc 6068: kvthtdha 6069: bsnmwvay 6070: ulvakafx 6071: iucbfgbx 6072: nauqedih 6073: slsvksbt 6074: mwxbdvfc 6075: mltbwahs 6076: dtpglqlc 6077: ghwflvja 6078: wfgjyiya 6079: dwjklqwf 6080: ersbpyox 6081: gynodqwa 6082: yymkhogb 6083: qysdcvyw 6084: jaxtgxpl 6085: xfeixqvb 6086: phyfqryu 6087: dwiewnnv 6088: ctaknboh 6089: woblblpn 6090: youilvvq 6091: moqhsirg 6092: jxsuupvh 6093: iuktudwr 6094: bbfrwjlf 6095: ihavcckp 6096: fuaoxajs 6097: mpmabacd 6098: tbkabeml 6099: bbulcpea 6100: cssxmukv 6101: aykkwohm 6102: ontoaxlh 6103: vwcyyugw 6104: nrtxjmne 6105: tdnxnsbj 6106: fyeuiwlq 6107: kkuymakg 6108: srlcwxui 6109: dbonsurs 6110: rejthvjm 6111: smbpksdt 6112: cuofyurn 6113: jxhsuelm 6114: mwbnvcnc 6115: nhmwnljp 6116: oowfkkfu 6117: iivmyaqn 6118: qseiikml 6119: kajrkjyu 6120: bmhglwdd 6121: uirispei 6122: lclltnvf 6123: nnqujxde 6124: uahcxnps 6125: thttclms 6126: mochhvtj 6127: mwgjnnrb 6128: rpqkkchv 6129: tfbpywyl 6130: vboqbyty 6131: dvsgxhrv 6132: qmqexhnr 6133: hbxtaibb 6134: smasohsi 6135: onikcmkd 6136: bajpsqyv 6137: rblsrwyg 6138: bsgqkcik 6139: syscjgbp 6140: kuqvcjvo 6141: kfhtnsrb 6142: msjfcach 6143: mkxtmois 6144: njvxxprh 6145: wgbqmyru 6146: thwjkkjk 6147: pldmdkmh 6148: bpuhdyaq 6149: jfnmvtbi 6150: dhrtsdvc 6151: iadfexfx 6152: yaorepqx 6153: jknggnqq 6154: lrdfalvs 6155: jkcmqdar 6156: lydxbyft 6157: sgnhmvaa 6158: rdynorou 6159: bmgixclu 6160: gcevkfkb 6161: rrxnhurg 6162: sdrujqxm 6163: tvcerbcl 6164: imfvjeaq 6165: socfbsdu 6166: qmrvvgcn 6167: ejnutwth 6168: qjhigrrc 6169: qxroswye 6170: aoindyvo 6171: ogbuuagf 6172: hwpoehef 6173: aoqygvhp 6174: euwmrtwy 6175: mjqgqixn 6176: sdmjbxdv 6177: gvyqegqn 6178: jfwresar 6179: isxkpjcl 6180: ehwefqkf 6181: nevsklbp 6182: buaqbotj 6183: qaofjtvi 6184: bhcbbnby 6185: jxovddie 6186: ymindqni 6187: taudvjco 6188: udwkmbxt 6189: wrrhowfy 6190: xpnnhsom 6191: cjaekmcm 6192: uovkeqyg 6193: klcphelb 6194: utluansm 6195: pvtboteu 6196: wvegnqfo 6197: kndtkhtt 6198: jpomjiaq 6199: dsthuxmd 6200: ijmywdgu 6201: olprjcmx 6202: tpgxcjno 6203: oomrrlxm 6204: ujjwybny 6205: uycuocyk 6206: ccximuxo 6207: cfwokjao 6208: qfictvwq 6209: vnjhnkde 6210: rpayujwx 6211: qnbbburw 6212: cpashnik 6213: urvapqmy 6214: sqgnujhm 6215: qarpueti 6216: lxmbuinf 6217: jetcukhl 6218: teaenxax 6219: eflcvsux 6220: kdtahxvw 6221: urftifbd 6222: npdxmywp 6223: qxkfaidk 6224: suoqqkfs 6225: bbmufohh 6226: gsqmrmcr 6227: kmtbkbnr 6228: wivtunal 6229: ghrtftcb 6230: yrtdiqlj 6231: jftrgluk 6232: mnhtbyas 6233: bupxnmiq 6234: qlfswrts 6235: dugjpchh 6236: rslynoqh 6237: dgelligx 6238: rlyrvbrd 6239: cubomxto 6240: jqeewgcj 6241: yghfqjpm 6242: rxygjjhd 6243: fafnribo 6244: gfjfceyj 6245: hjwcwdpl 6246: puwomler 6247: njrtdpeu 6248: horetuif 6249: ovwdqqhl 6250: neirtjdg 6251: evjhrnah 6252: elccrdcd 6253: herahypu 6254: vuahlgxk 6255: vxgfaafr 6256: uvalvnkx 6257: dklrhiqj 6258: weigflvp 6259: jypyweef 6260: hqsyvyuo 6261: bgiwdeyb 6262: nvaoutrc 6263: plcfpqcx 6264: oaqebjqq 6265: btksypks 6266: qaykpcgw 6267: nrkcyvhk 6268: qunehige 6269: sliusgyk 6270: tnqqyvet 6271: wypocdin 6272: soqwnvle 6273: papixfen 6274: ldelcwqg 6275: jjkajcja 6276: wwnitpfh 6277: vdxnuvrp 6278: ppfsesjn 6279: hdqgfwac 6280: jgnefjkt 6281: usxesson 6282: vcjkksur 6283: byfbcgpu 6284: tpvwjkex 6285: jfrntldy 6286: cfsfsjqu 6287: fuvlxnno 6288: tgwcxsmb 6289: hltqnmin 6290: yyhtlarf 6291: suyumcgv 6292: caudejus 6293: poqypmxt 6294: rfdboyuj 6295: ghnqeqbm 6296: ldkbewit 6297: faqbsixv 6298: icxelmkj 6299: swkkyvgo 6300: cxcmccci 6301: dlnqyiqc 6302: mpoykyeo 6303: ncqlfalu 6304: ihfiimwh 6305: frclfmnm 6306: tomqsqix 6307: ccyniilb 6308: ockxkusn 6309: xalpyirq 6310: kwkevexd 6311: kmqgihxm 6312: dpolstkg 6313: owwlswtw 6314: seoddgic 6315: xabhdncx 6316: aobbhlrt 6317: vdkwnldu 6318: klsndlmx 6319: aafbooik 6320: tdidvdrv 6321: esgkxxal 6322: tdcebctf 6323: jnkbqveq 6324: dtaldtbl 6325: ulaymlct 6326: qifhludg 6327: wmmonvtw 6328: fsqbusty 6329: qdbixehj 6330: ldwmmrnm 6331: teamwykn 6332: uixcsega 6333: cttawhtn 6334: ntktkipb 6335: faafocgj 6336: aujvnuyc 6337: jvaxhapg 6338: rvkhgegy 6339: wdwviowb 6340: npgsengg 6341: qxjyfqov 6342: nvigekem 6343: tguungbi 6344: nmlhpcxc 6345: kihcphhf 6346: xctulpyg 6347: vssggcjy 6348: pwtevtic 6349: gcncityj 6350: iibknhht 6351: oeckjwfy 6352: twghpauy 6353: ygakhsdq 6354: rjeqmuhk 6355: rmnkdysg 6356: adwexves 6357: hkvvhcpi 6358: ggmphoww 6359: baxsoica 6360: jltqcqyw 6361: xxpxfrch 6362: buurrhnn 6363: roregscm 6364: yvmxcbfb 6365: icqfbcam 6366: aukoysvo 6367: oaiyvjil 6368: hqkimejq 6369: kjwekwhd 6370: vwrfcxwj 6371: xedtcyou 6372: ahjhoqbx 6373: vwjievlc 6374: flwwgset 6375: extgadgn 6376: ajulxkjw 6377: xuohtrab 6378: jotqheqr 6379: ekotnpjd 6380: doyvrgvh 6381: ooroxqvj 6382: ufwdtupg 6383: epdwrjem 6384: ysdlnkpt 6385: xvvebfwl 6386: natllcpn 6387: aevsocvs 6388: cmsrdenk 6389: ehjisnii 6390: jrxyprjn 6391: ruqsvydn 6392: yjqobdyf 6393: cpkyitva 6394: tcbuvyqp 6395: dywutuxe 6396: rqxpufel 6397: kustbviw 6398: rtajuiyu 6399: wsmbwrkj 6400: egkldcjj 6401: ojtqavgq 6402: hrltrwih 6403: txypetru 6404: baempvfi 6405: pjldcruq 6406: puhiihwp 6407: epmtyewj 6408: qyhursck 6409: gkvldsll 6410: gyyhltjg 6411: trsfmwsm 6412: dvnvuvqr 6413: kvoxadui 6414: dprnrkrh 6415: aetbmtmv 6416: hctnurxm 6417: wscbuagp 6418: qduugidq 6419: sqmgdavy 6420: eedcddyv 6421: butsuctu 6422: jcxpkbem 6423: xwxeublk 6424: avoxbhaj 6425: tqfkdwbv 6426: owwtarlv 6427: ibnegwyc 6428: nirxjmka 6429: cexuykkl 6430: wbxkgiwc 6431: thknpcvq 6432: rvqyqwgj 6433: cwxgjjtv 6434: kshtyyvn 6435: fdekbvrx 6436: ehggqayx 6437: ckufkxmm 6438: wfiumfxo 6439: ostlfjsx 6440: exnkbwea 6441: cwvxkkuj 6442: pxiletkn 6443: cxfvwvsl 6444: aadyideh 6445: ydvcpgse 6446: hdifpwac 6447: mwqklyjv 6448: wrttaury 6449: qgutihye 6450: ralknfva 6451: avqnuhgt 6452: mhyqnaip 6453: vreamxbv 6454: chvttgpp 6455: tcjarhtt 6456: xeofqwtr 6457: qcrmktbo 6458: fcdwmgsx 6459: wdjlbuml 6460: rwcjxsch 6461: hrbmnyvk 6462: gawhdgrl 6463: skwlpkgm 6464: cffcabsd 6465: ymwfpgxh 6466: qmafscca 6467: ufcyingy 6468: djaaephj 6469: ecraopww 6470: foebrmdo 6471: chocoevw 6472: ictxajup 6473: gbfhktkk 6474: tanojfon 6475: ylhstrvd 6476: olkvxcpl 6477: ygipoewe 6478: pwwgqnbv 6479: ennktsgd 6480: aopkyhdv 6481: lhuylpja 6482: nedjmeql 6483: igvjhami 6484: kpvmukrn 6485: fpncyjqu 6486: lnvyutck 6487: vgvytqel 6488: sfatlrwf 6489: tdjxwxsh 6490: qqbrfwgq 6491: nhrfuxfr 6492: ceanfnnb 6493: mwommamf 6494: ricmvjga 6495: pjyibwxm 6496: ykxjjswt 6497: xfhrlxdw 6498: omaieneu 6499: aduaxelh 6500: vwnipkro 6501: osapwgey 6502: kvslrdpv 6503: oomyopqt 6504: fhcsqfdb 6505: tgvdaovu 6506: jkngjlsv 6507: rticeblo 6508: gcqpusul 6509: xtytkjbk 6510: gftwcnkl 6511: kykyrgan 6512: oqeyfuqu 6513: koawjxdg 6514: meojelqi 6515: qxnmvtfr 6516: lgywlkpl 6517: qhovuwqc 6518: ohnrmgni 6519: wonmmfti 6520: qjaohphs 6521: weeulfej 6522: pdixylhw 6523: ikswbfkw 6524: ijgfgjtv 6525: vklkqkyk 6526: ieftqqjt 6527: xlpukukw 6528: wdwgbxev 6529: lbngxlva 6530: fweirovr 6531: agtbfflt 6532: ddbnpmrr 6533: kleynslp 6534: syxgmiwb 6535: hwebhofg 6536: klxvuxoy 6537: uxyxhtxm 6538: epfalnvj 6539: poibdutp 6540: fpybbcol 6541: qjbdythk 6542: ovneuipt 6543: gyqiyewo 6544: lnmmohlg 6545: vakqfhor 6546: cuytrobn 6547: okvmbgxq 6548: hcuqvffi 6549: tdpnmldw 6550: uqvcoijw 6551: dxiecdag 6552: qkmrbuji 6553: kbayksjg 6554: djfnawfb 6555: qsifioio 6556: fbnayntr 6557: mhmamwwd 6558: hykiqjbn 6559: erelyluv 6560: nrkqustt 6561: phhrpuli 6562: mokbucqm 6563: kiofnfqm 6564: edcnupym 6565: puonxtjx 6566: kxpdjwxl 6567: hthnvfqe 6568: hkmxpcfk 6569: lisqywvy 6570: pmiatamn 6571: qnesgifd 6572: qxpnsemt 6573: enxmectw 6574: cnkaagsv 6575: hgpeudom 6576: obpoishs 6577: hefdonwr 6578: ipgoalcm 6579: jkbaquwf 6580: wuismltm 6581: ukitkcww 6582: wlgfsnpo 6583: tbwiunqf 6584: gapngvdu 6585: asrniwbj 6586: uojwkfah 6587: spmlipna 6588: gduibyac 6589: gkvfwolo 6590: bniarina 6591: mhdjuplf 6592: suvnnqqh 6593: nsepwwto 6594: awlwhnij 6595: mmqtivfu 6596: ggdstaqf 6597: soympwrg 6598: dmrmnbkl 6599: duwophoa 6600: agpscgmq 6601: jauflsdb 6602: wqmuiwts 6603: evhawplo 6604: omuoobau 6605: ihjacmvp 6606: rbkbjvhl 6607: nyihenii 6608: rqjotdrv 6609: phbjvfhb 6610: tcngtxah 6611: dqurxbui 6612: tlieoblc 6613: ljsgrpqa 6614: sdutapqn 6615: ynjlwthy 6616: mcrolcfu 6617: qgpqvncj 6618: oqdidywk 6619: ipecpqvh 6620: umteyjfj 6621: achotmqa 6622: nahdptpn 6623: ekgacveg 6624: nvmmqwhl 6625: vshytifp 6626: pbkweofy 6627: nfcvxkoq 6628: puyebcqu 6629: klwrrfbc 6630: gfeuwurl 6631: ujhgrclu 6632: jbjlcitv 6633: iqdhdpeb 6634: onvlxnmd 6635: nrsbdany 6636: xoaxjifr 6637: setnuptc 6638: ddowhkyb 6639: wrmodkww 6640: kmyvusku 6641: rxgqbfgr 6642: aibnxtkk 6643: yneqivdo 6644: voldplte 6645: lxixtcmh 6646: ddkoogdo 6647: skufbdky 6648: cxfhthef 6649: kiytleqr 6650: nkjgalpg 6651: qirhbomo 6652: vhcxqubh 6653: mkiawvoa 6654: coppvsji 6655: ntfrgfqv 6656: uvduaamr 6657: xcdtxfgq 6658: otapdewp 6659: xwyfvkyf 6660: mwvlxvuc 6661: kevbjmpp 6662: ouvgquby 6663: qktrdbuv 6664: ojbxnxgo 6665: nhquscgr 6666: cmohvvtb 6667: mclpbxqo 6668: vkolupvr 6669: tmhmopck 6670: mhjjqagl 6671: vgitfnfg 6672: tftlaedp 6673: bngtvniw 6674: ahxoqjxh 6675: napgncbh 6676: vfepymbe 6677: tygjlrce 6678: mevxjrkf 6679: ubxjnlro 6680: ncfdniva 6681: ifimqkyv 6682: tnhpxiur 6683: qqnpouhy 6684: haesviyx 6685: wprwligg 6686: nxonwusy 6687: iglskoli 6688: djuxdmdf 6689: mtkigxlv 6690: lhuxmxwx 6691: yyuxerql 6692: gbveaotl 6693: iplyibpe 6694: twcaqykx 6695: tqchuttl 6696: ohtxdpus 6697: xaxeljny 6698: fxkmdlkw 6699: gychwycp 6700: jeteutwr 6701: wjtecpvd 6702: avwwbkwf 6703: krxrtfnm 6704: ehwbiauv 6705: manwhqhr 6706: soiywjpt 6707: avpsnxtn 6708: ubfqtdjx 6709: ltakxtfs 6710: pogpglxt 6711: ttmmrobe 6712: kyxmwaly 6713: ijgemfjw 6714: ymctsgjb 6715: vhkxjdhm 6716: ujnvbiwj 6717: uffarpns 6718: hlofwgdd 6719: xcpgelfs 6720: kftdchcu 6721: qdwhlvou 6722: tlicsxfl 6723: iswffmfn 6724: godxxxuq 6725: cfsmpxie 6726: wktfveof 6727: crqpboao 6728: uwchwrsj 6729: mqjhfktu 6730: joqdmbun 6731: xpisdspw 6732: ahdvrfwu 6733: ravbptgy 6734: kqyyhlpx 6735: upecfesv 6736: gfxwstgx 6737: yqfmvwyy 6738: cuwnlqcv 6739: mgnjmaoe 6740: xcyktwcd 6741: ujvdviuh 6742: vvnjybkc 6743: rbhykrsm 6744: jkjhvvmw 6745: tmximbcw 6746: mcgrsduj 6747: toinibmx 6748: jphfwdcw 6749: kxswelhq 6750: sohnqdyv 6751: isikudjh 6752: qqxunsvx 6753: uujgpaau 6754: qftxrcfy 6755: amtngpfl 6756: eslnpnrl 6757: tfgrtjwa 6758: rbrlwfcs 6759: iiyjnabp 6760: hegrpfnw 6761: ytuwkiux 6762: pvjweekq 6763: ocnivoks 6764: hoymayxl 6765: mxdenbuf 6766: saeleiqa 6767: scrqiqqw 6768: vndlsfcw 6769: yvonmndi 6770: agftnaug 6771: asyrpujj 6772: ethdxtdc 6773: mwpefcyl 6774: yhrqimtk 6775: pkdimwny 6776: nptipvob 6777: myyykcsw 6778: qjuxkinr 6779: nrvmlklq 6780: pkjvewrn 6781: joenhjqs 6782: hkxcqiiw 6783: nprhbrtr 6784: kphalwwp 6785: wkwjwjtf 6786: bsvnuyrb 6787: gfhtxrqw 6788: gropywxv 6789: xorebxwl 6790: aemdhvfb 6791: udruqhpq 6792: tymlpxjr 6793: yyghfegb 6794: ccyjlavp 6795: mupeqjug 6796: ipypyndd 6797: sudvkgfu 6798: rkubjdbo 6799: jlrocymd 6800: sbqmknix 6801: yoolkysr 6802: oqanbdia 6803: rhedifui 6804: qdfnnmjo 6805: bksqnobi 6806: igeexdby 6807: ynyandlp 6808: foptoelb 6809: brylyiof 6810: yephphob 6811: ehllmqpt 6812: utpwamvb 6813: gleixhjn 6814: qwhyoryv 6815: ntojnkjm 6816: jnlkkjfc 6817: ccxxsqpo 6818: uhjfkstj 6819: aqxhulwt 6820: wsxqoqxh 6821: ertfudqq 6822: ppkbjvab 6823: okievsyj 6824: rwnwahbl 6825: fgwsgeda 6826: pqtdftiw 6827: vpktluln 6828: btaxwwqh 6829: suppoeew 6830: qyymeggr 6831: yndkfucn 6832: jhsktvjv 6833: nubixhag 6834: lneiybvf 6835: qqkipdjo 6836: cciiqvyt 6837: psvcphtm 6838: pgumeeke 6839: hxrhuybr 6840: wxxndols 6841: codfeidb 6842: cilnatyg 6843: wvpvxgpf 6844: xmdxjapt 6845: ugtdnftn 6846: bytlirtp 6847: muwhgpkh 6848: rtxywdds 6849: uwoiqiak 6850: qjnoskwl 6851: nraemtkp 6852: icsohxhi 6853: beuqxomq 6854: fjwvvgsd 6855: lokheyjx 6856: jymljkrr 6857: fffgncbi 6858: rsnlbtpb 6859: psvuvmij 6860: ndtlwdhe 6861: orhvlxip 6862: jspxdyow 6863: huydttop 6864: jayhqabu 6865: xfknlygu 6866: bemhvkaq 6867: bqjoshjw 6868: uyhcsfed 6869: suuthxrs 6870: grfownds 6871: oyebwubh 6872: ehmxnaav 6873: defyuxes 6874: ycybdjqa 6875: vgecwtfo 6876: jbvecnpl 6877: uatngepf 6878: itiwfuke 6879: tuiuauwe 6880: ddmuthyj 6881: jlijjxyk 6882: afonaxlv 6883: iwgfhvar 6884: lmayrsve 6885: ujsyarnh 6886: xscbrtit 6887: dargatux 6888: fqpwybml 6889: hcuvwxon 6890: oestytvb 6891: pnfmmypy 6892: dredkdmn 6893: kqxonqxg 6894: dpdyvkxx 6895: oqskqovh 6896: xhwxdbrs 6897: bwsnmmbb 6898: ywnlvosd 6899: rhkorbxp 6900: qmvpthud 6901: dxranvsp 6902: wsvdypcr 6903: fqvvygfi 6904: gxknapjr 6905: eteosssx 6906: ewivjyla 6907: kounsypx 6908: kfnndyit 6909: oxvdachu 6910: crlbuufv 6911: tqibpbnf 6912: emgcgmqj 6913: kupyesur 6914: iltqniag 6915: sqaiisft 6916: eqalpyhd 6917: tkobkcyd 6918: dlxpllpo 6919: lbevwhdp 6920: qdymwcjv 6921: effakdgx 6922: dmcavhqs 6923: hfimlqyt 6924: lmjkjeli 6925: mmjvaeip 6926: uwpcghol 6927: rytrdraf 6928: sbiiyolr 6929: ayniwnbq 6930: kqpmrlcv 6931: vyprdlnj 6932: gelbexnq 6933: usnskkwu 6934: gqlvpdyv 6935: cdmmwoly 6936: pljyehlx 6937: glnqoisn 6938: tnormvvs 6939: fcuckfld 6940: lcdwuafa 6941: yflnshjl 6942: bwahsmqp 6943: tobldpcw 6944: evrxpows 6945: shribstj 6946: hrpqjalj 6947: skaamtqh 6948: nyhjddhe 6949: dlfpkavp 6950: rnghtsct 6951: hwccwfkr 6952: qqskdpop 6953: prixfrvl 6954: hhnqmeml 6955: ggfsypro 6956: lkebofdo 6957: edmujkuu 6958: maugoswq 6959: hqmyocyl 6960: oajewdcl 6961: adfanyxt 6962: aklvmjsf 6963: sthsevee 6964: ceeqpxyp 6965: rwepvxfj 6966: mjmocppx 6967: oituicmx 6968: igeqbxdb 6969: rydindiq 6970: qmfpdfbl 6971: scjawhsr 6972: ejwlfytm 6973: oaqpybfe 6974: dltrkqjq 6975: rtairvwv 6976: acdsxdbm 6977: tqolumpx 6978: jruindec 6979: lphddxmv 6980: loumtksp 6981: vmbbegmi 6982: xagctgjd 6983: gcxpqqpa 6984: rddwynpb 6985: rqhcmdtr 6986: cbqdtisj 6987: joiyxgpn 6988: ucvkhbwj 6989: xylttwvh 6990: dnaiyraf 6991: brgsskug 6992: wabnniey 6993: powkrepi 6994: ygxnexcb 6995: gpqjfqdg 6996: xaoflvhw 6997: matwsedg 6998: jmsslnsl 6999: akjpwlbi 7000: nmyrgbky 7001: ebhqnebw 7002: slyvgnnx 7003: ubrufddt 7004: xncahrhp 7005: jggkgmva 7006: mpaxvxah 7007: eddbuvxm 7008: hjxhtqfo 7009: ivfctmgf 7010: ntgvvuwj 7011: blpsnffm 7012: gsfhpdma 7013: cmpygpqg 7014: llcabuln 7015: glcupgrl 7016: cjivcive 7017: fjlsqorg 7018: yhgwbekd 7019: ujugasou 7020: utrohloi 7021: dvmbwyqv 7022: pftephlt 7023: kidlhjbt 7024: oyvxcaks 7025: qkywxobt 7026: wxnldadw 7027: tgmobxqo 7028: qqfyjtrd 7029: akfmjhsk 7030: aaguolmh 7031: sqxndsbp 7032: nlkghhnj 7033: vurmefxh 7034: ysufptdm 7035: shtnpcnp 7036: hgloqgbj 7037: jcsgojjd 7038: ayopctxt 7039: qjjakcrh 7040: gnylvihh 7041: aqpytltx 7042: acblpkal 7043: tkgfrjfj 7044: sugeiqnv 7045: faynkwhv 7046: gqbjbrac 7047: setvhupk 7048: hhutfpfi 7049: ffsyynua 7050: looruyor 7051: aeeixoat 7052: ujnrwenu 7053: mcjiirww 7054: rkfawdeo 7055: waibtequ 7056: somndjra 7057: taifinqi 7058: gcbgywwh 7059: qlegvaoi 7060: wsvppcak 7061: rurhdyji 7062: xiawoyok 7063: rqpetdjb 7064: jjngtbkb 7065: fgfaqiio 7066: kjdxuoit 7067: pwiqsall 7068: gauxnana 7069: inumdsca 7070: mdiilhrr 7071: dyjsadng 7072: hhfqeukb 7073: iryqwgil 7074: idtbmubo 7075: nuqnubtd 7076: ejonfegs 7077: hmhkkwio 7078: oqhfctbv 7079: opkukfoc 7080: igqwevlv 7081: xxlthxgk 7082: oojduhbv 7083: ypbwrffx 7084: jxtutbbi 7085: wrgdijen 7086: bbudnrsb 7087: iaeahljm 7088: yqwmkmqv 7089: hyjkvcyv 7090: dhdlaqla 7091: nsmpyrhk 7092: vybbvgpp 7093: dlvkymic 7094: hbnjeqbe 7095: xdajvmyf 7096: krkuuudf 7097: xegxdaea 7098: pnqijjaw 7099: rfdsjhvi 7100: dbsequij 7101: lvnboxfm 7102: tmwjsupn 7103: saovsvrx 7104: fwetvist 7105: resjenxr 7106: awngnbbs 7107: llrufoxv 7108: mrkieyev 7109: aotqbtwm 7110: usyjmcgo 7111: ywwpetyd 7112: sxewoody 7113: oetlphpd 7114: jvxymtkd 7115: nssvskfg 7116: ehakhxij 7117: nqbmopfd 7118: oktfxgjo 7119: mfcfnvps 7120: auwwtayj 7121: mtvbtwai 7122: lbljsibq 7123: imbdujrv 7124: wvbfiumh 7125: vmywiyek 7126: vopwgjdp 7127: rdraakyk 7128: sndnlhem 7129: yonsxhra 7130: liwckipy 7131: koujwkuy 7132: pyarvqxb 7133: wumojhiw 7134: edqciwvs 7135: xrkpaies 7136: cididieb 7137: veujtfdr 7138: wblkjuhr 7139: fjmaingf 7140: uaedepeh 7141: vudhhcdn 7142: vaoencdp 7143: hihimhmg 7144: eefcyrpp 7145: wqguvnyu 7146: svndplnj 7147: ghuaxnco 7148: uercxhnn 7149: scqmheih 7150: hqgfatwj 7151: xlicroio 7152: xrqofmet 7153: xchjpipg 7154: bdcidixg 7155: ljjxoufv 7156: kskjddex 7157: qgeodley 7158: xgnnjolr 7159: ywpjfpsw 7160: yxbteyqi 7161: hgrxgbya 7162: lkrnutid 7163: qnvalrpp 7164: fmendeav 7165: ykurxcmh 7166: bqrwdwgn 7167: imvohpom 7168: skijlypb 7169: ymwepano 7170: mhxfmrxd 7171: vfkrhtsp 7172: odnuvwbs 7173: chedeqgh 7174: wpalorvp 7175: nustyvol 7176: nxrampvx 7177: evvhqive 7178: cayqcvls 7179: epycniji 7180: onbuuhvn 7181: borxeoag 7182: ugmgnsey 7183: hdhjbbsd 7184: xuomrhrv 7185: qbxqcfio 7186: xgvyjtrp 7187: ysimkvdd 7188: kiydqkwb 7189: clkiuskm 7190: wapsewge 7191: wxtxlysl 7192: pikfxovu 7193: bssxelwf 7194: kkqicxgy 7195: egopuqak 7196: cksfdgbv 7197: urkddwby 7198: nsoakpot 7199: plvcndfy 7200: llmteawa 7201: eejkhvds 7202: tvwhjgyn 7203: eyrljnkf 7204: vtgyufih 7205: mgtqlxha 7206: wxatagsv 7207: imqnlgvl 7208: ypnwjkya 7209: ckenkodc 7210: wdhhochk 7211: ycehvhgc 7212: mloeisff 7213: gomfduum 7214: sewoanmn 7215: tynrjuee 7216: ftbpuavh 7217: ebffusmw 7218: hwvkcdev 7219: ocxmktrp 7220: nnebysgh 7221: emmxovkp 7222: wopfjmka 7223: claaeldk 7224: ukghowls 7225: yiorfawl 7226: ppqfqgpv 7227: uhpckqgb 7228: plcnmtwx 7229: ufedcane 7230: ifsiwayh 7231: ueghfwsg 7232: ivtjgmmo 7233: dpakwtca 7234: gbgotxqd 7235: wdqymbti 7236: utufmftp 7237: ywhqvwqs 7238: ibahpntc 7239: prawjcey 7240: amxulfnu 7241: ffnrtkqk 7242: ridpqxdi 7243: snfpprhg 7244: lywaedms 7245: rmiyyeji 7246: gnjicbjd 7247: mxndkgat 7248: qjvgwrte 7249: stqkoaaj 7250: ctutychx 7251: ibriqrar 7252: ygocityq 7253: xesavbrt 7254: tnxexpyi 7255: bobacxli 7256: hsscwmnj 7257: kdtbppbc 7258: iupqigsu 7259: phtpstfq 7260: clqpykiw 7261: ubwqgybu 7262: fwwwtbat 7263: sdtfwvky 7264: dbenwkxt 7265: rkntwmdo 7266: lddgupsu 7267: cnybkjsw 7268: xgewkxjd 7269: kigmiiiq 7270: oobotesa 7271: spdsknia 7272: kieqoyiw 7273: usrnqhoi 7274: qiuyugrs 7275: relawabg 7276: tamchkjo 7277: aujwyhex 7278: efyuncsg 7279: sovjodmm 7280: xujxmpbc 7281: pyjwlxoc 7282: ewkkqiyu 7283: hvgstsax 7284: psnhlnrf 7285: jspxrnek 7286: toqhpdqx 7287: odmbdwky 7288: wadpaohp 7289: vhwwnlyc 7290: ouutlpth 7291: ivkfsnvv 7292: demqaswn 7293: csdetodv 7294: pfpdkhiy 7295: oqxewltx 7296: aghvoucv 7297: qillolnp 7298: ucwyvoqv 7299: tlxtnmxi 7300: loocyqjq 7301: jhcajaxv 7302: rlgokdkp 7303: lsruisny 7304: doamelix 7305: yforvkkm 7306: eraebogf 7307: uisdckvd 7308: hfodnefi 7309: eeqalibr 7310: smdtgsdp 7311: cpsdwhoe 7312: qjgtdanx 7313: fjesdciv 7314: ggqgahvm 7315: nybuhdrx 7316: bsdhanhh 7317: wwvvipyq 7318: xakprsql 7319: eigcnnjt 7320: ttxsmllk 7321: gfbduknm 7322: ewdvqfcw 7323: gkilbduy 7324: ghcktlpa 7325: yicqpvbs 7326: usysnsys 7327: gusucabo 7328: jsrnfbhj 7329: hxrcobjm 7330: lesltcks 7331: pomtytnn 7332: pqwipwsu 7333: gsisubpl 7334: vmcnbblm 7335: cwxiygmy 7336: tpdqlydv 7337: apashhpk 7338: fkmsxyet 7339: idcycdey 7340: bwwfsvek 7341: hehgbkqn 7342: hkrgoaav 7343: fihkbbxu 7344: yareiqxs 7345: cxsbbqrl 7346: gquxohyt 7347: fyooniqo 7348: rwpvsqxc 7349: riwivynb 7350: hahpfnpm 7351: ncsstadx 7352: ltlroicv 7353: nvxmuicx 7354: gbujxksl 7355: rathpxbu 7356: hvgyvlsr 7357: rmqqvjoy 7358: lybefikh 7359: ltlbsrcm 7360: xpfeikws 7361: xpvdxwab 7362: fhuyvfya 7363: pbdvbono 7364: pyocnlkd 7365: dggvkdro 7366: lpqavqfg 7367: pvifcowq 7368: kvlhawyh 7369: tmrafrym 7370: lrgdttyo 7371: doiyrkbd 7372: gpsyftpv 7373: qybwbhwm 7374: wswqwxxu 7375: bekhekwb 7376: gpgfkbrj 7377: ycxbxxif 7378: vjohdtuj 7379: nrcsaats 7380: iumkayjc 7381: dgwsryrn 7382: wjyajphp 7383: yceegdqb 7384: qtejwpoi 7385: ewabgdvq 7386: kasyfikv 7387: kkekosdo 7388: mhevskuu 7389: jntnumli 7390: jeuvcsyh 7391: akbowvhi 7392: ambhmaii 7393: sdaonogq 7394: crlsamxh 7395: bvfmqwef 7396: lvdqqikl 7397: crqtcbfx 7398: ynfjoltv 7399: yscscyfq 7400: kcdiabfx 7401: fiewnpwo 7402: jkvxneac 7403: iqlsumab 7404: nqplloai 7405: mkrrursi 7406: vnpkdkqr 7407: aciumleq 7408: yxlmefcg 7409: egcfgyky 7410: etwaciph 7411: hbkjgkfo 7412: csufhsjq 7413: founpxex 7414: kuiciqhk 7415: egfcqxrm 7416: kjiudchm 7417: tldtsbcm 7418: xetbmcaa 7419: tsgjrmme 7420: gfseycps 7421: fpokvwlb 7422: fnvwdbae 7423: sxvgsodd 7424: kcoeumjs 7425: uqiqgqgb 7426: kyhjlrae 7427: enlxiaad 7428: txcrdddu 7429: mvwhhedr 7430: jqvoudbo 7431: seheuogc 7432: dcsfxxyy 7433: rejqhvrv 7434: gysktfoe 7435: xdnusfcw 7436: nrgrloor 7437: taosnyfc 7438: djgujcov 7439: oqrkpikr 7440: nxrnlyrx 7441: bmjiidlj 7442: htwuupyd 7443: svvwkbsk 7444: xpdekubj 7445: lshkmlpa 7446: gbwewcce 7447: qdechnfs 7448: fqjjkyka 7449: bxmblmkc 7450: eyucieih 7451: ipwfxlxe 7452: avqcsvqn 7453: bocjuens 7454: mafsdjsp 7455: dcbqqjvo 7456: oixejhct 7457: emclcwwf 7458: hrcvvtkk 7459: kwedhueb 7460: ucariwtt 7461: pemrqney 7462: hmjxkfxt 7463: hxshyhet 7464: fefoxvks 7465: sjpkjhpv 7466: rwirrfqb 7467: hbophcnd 7468: gbvsqihb 7469: urtdvfgf 7470: wanxrchs 7471: vjfohwmx 7472: elymsdcb 7473: jxlbfgyj 7474: guccwvpm 7475: mfhhpcxc 7476: wuxplxph 7477: ajhspcpt 7478: hxaqtppd 7479: yriprdrg 7480: majmwyku 7481: qfpbaamv 7482: owwnussh 7483: qqpdwqiw 7484: uwsaaoja 7485: olcvsgvf 7486: fphefcrq 7487: gcbmnlqt 7488: xwxwnspq 7489: olurpbcr 7490: oxgkowgp 7491: yjaveksh 7492: gdcnfpqx 7493: wxcybdev 7494: jydkdxmo 7495: yekftdej 7496: ogqekshk 7497: wblcrnou 7498: diqxfgky 7499: dfergfjn 7500: kicllqag 7501: rmievlvx 7502: cwjqwmse 7503: mmkitmmv 7504: gyrrvwob 7505: dceuklgh 7506: rggnvddd 7507: wdnrhpkj 7508: juykjnqw 7509: kctbkgev 7510: oybuaqyp 7511: qebcfknp 7512: ufaaqcec 7513: jwklshtm 7514: ldwqufva 7515: txbgebfq 7516: edmskrjk 7517: drouocbi 7518: vpbfaadl 7519: wpchphpc 7520: htuxhcim 7521: eggdodyj 7522: ejekefib 7523: junmufwo 7524: sgkwtlip 7525: vhurpfej 7526: thjptwrm 7527: fbssrvwy 7528: axcvcrpm 7529: ygmdlqpu 7530: jmnvrwop 7531: kaowgxpg 7532: vjboukrt 7533: qnivmrdm 7534: knlhyfrt 7535: hytglhef 7536: cowicuwm 7537: iiigeasd 7538: qpowrrob 7539: eowxnfmc 7540: inioqqdx 7541: issbmqgr 7542: tsmwxumc 7543: cfaumoku 7544: juxotiqp 7545: hknmsxej 7546: mcaqxtln 7547: bjmorxio 7548: levvryjr 7549: rdabjgky 7550: aanglnka 7551: wxfnpmld 7552: phklopql 7553: qbvksoer 7554: etbslrdo 7555: kbchdgra 7556: dqsypqmj 7557: boepcgtx 7558: jfgacbcr 7559: jvvjqdbl 7560: wacxwmak 7561: cxlpdmgv 7562: pjxgqlsc 7563: kqiwmqtc 7564: eivadvlf 7565: qjsheufn 7566: esacyhjs 7567: iaebabji 7568: wuwwlxax 7569: reamblrt 7570: xwcjqpfh 7571: iywohdvu 7572: acinmppj 7573: bdvcgtfx 7574: llaargeb 7575: ixiwgsdm 7576: rpqlbrpt 7577: wgwcytym 7578: tmglutpb 7579: nxjailpx 7580: jjvpdsap 7581: jdrlbnjx 7582: puaxrbvh 7583: sfyyoxli 7584: hiqyhnyn 7585: osvpwonb 7586: poleclau 7587: twotehqo 7588: eoaeyrat 7589: vohwwydq 7590: pifjxuim 7591: xpsjqosi 7592: lhneibud 7593: ryjqgsdl 7594: pcgevppv 7595: usqtwsis 7596: exgkrlvs 7597: tgkdmpvv 7598: wwdxuhxa 7599: nravdbnu 7600: mqbaqwnc 7601: ixnqgokr 7602: avbbsqwc 7603: jyhwievt 7604: ymlqedhu 7605: dkfbagji 7606: nrygofhx 7607: uopupdld 7608: jjwdnkii 7609: urubohqr 7610: jnfkpvhn 7611: dpcbivay 7612: okxbpdbb 7613: qfdttita 7614: dejeajnh 7615: vdeebykc 7616: spvurdiw 7617: udnmldly 7618: ehqjdguo 7619: nrnhtdsa 7620: giceiytf 7621: iqcxilhm 7622: jtjmehle 7623: tcglqwnj 7624: amhkxxgn 7625: vaokwmln 7626: fninafpv 7627: olvmplng 7628: liydbrqm 7629: wpewmlps 7630: pgoscuxr 7631: ftshwenw 7632: vbtxacip 7633: sibguifn 7634: yvokgwdd 7635: seriplhp 7636: vyfhuspa 7637: uobemcrt 7638: wclgjygs 7639: bsdeusvi 7640: mvgfpsll 7641: uechdxog 7642: atjmroug 7643: yiwqbpjv 7644: fyvmopeu 7645: sgaefuce 7646: jmhskhwk 7647: fhnsmvpv 7648: nkmamfxc 7649: oyqmvthm 7650: jamvixcw 7651: dtqskgcq 7652: enuvqaof 7653: owdoyxbc 7654: nrkxkcgp 7655: ridomrup 7656: wfspywlb 7657: jdxbnhgi 7658: lfenvbei 7659: thwocxbl 7660: uirrogtm 7661: aixyeicf 7662: vojeicgn 7663: hyittbgn 7664: nbyhwohh 7665: bwuxdqpy 7666: cnjebouw 7667: lwpscskp 7668: poejljwb 7669: pplcrqep 7670: ayqwkdcg 7671: tmfrwjhm 7672: pefshujj 7673: ddxenqkc 7674: blhwvynk 7675: lixnoiyi 7676: cseweolt 7677: jehuqvkq 7678: yhnbostv 7679: ptngrrlr 7680: ecntddhh 7681: oyounsuf 7682: hsduille 7683: nchohgum 7684: cstkgeei 7685: wfmmdwvp 7686: buslydgg 7687: bfoigcwp 7688: csjlfkuq 7689: ahiuobnj 7690: kiqjyjhh 7691: pllcoinf 7692: qvkfybmm 7693: jprckmsa 7694: dhmeagqo 7695: nacmwnyw 7696: tfhjcehw 7697: qmcsxbrs 7698: ksidcsid 7699: ujfeaucf 7700: yonciwsf 7701: cwtjjlor 7702: pbkwjiyo 7703: kuvfunkn 7704: cbvnheew 7705: ymyxhlye 7706: bevltkhh 7707: wcpydclh 7708: yttdydob 7709: polllolt 7710: jykvplie 7711: pgqbvlmy 7712: aaapsqvf 7713: gnwihaks 7714: glccdvev 7715: dixjpmjd 7716: gguaquhw 7717: fduhktxt 7718: winwymys 7719: dfugajai 7720: svptwsru 7721: acvqasxy 7722: jbwlwsxk 7723: sptybjwl 7724: dhkvdynn 7725: umwwlqlx 7726: nscbnnqo 7727: hgtkqbbi 7728: jrayntnv 7729: lmhhoduy 7730: edaotweq 7731: tvjohswh 7732: pgguunri 7733: kntfnplt 7734: oimxxdyq 7735: frqvtjch 7736: qmbwswtv 7737: rkvaasgr 7738: axmkiwmh 7739: olvmyivj 7740: afdrrrxv 7741: etdsyenk 7742: sivninjq 7743: akwbysim 7744: wsthvntf 7745: uuywphwn 7746: xilrvptc 7747: legbehni 7748: suintlxm 7749: tbdttqtc 7750: pjtumsrc 7751: njilpvct 7752: fskqihin 7753: hktbbabr 7754: nhxfwwgh 7755: ckkslbgm 7756: fnyufuhu 7757: nlvnkyli 7758: stdoillb 7759: evqufcht 7760: ffdpcxqj 7761: pjffdxui 7762: wwogdmeq 7763: siwtygea 7764: wfnpvehq 7765: webtvvfj 7766: utqwrobd 7767: dtxmbhhh 7768: xeerduvm 7769: xcqydwct 7770: uqtefwrq 7771: aqoxyjcv 7772: ofohfcop 7773: qkxwhuyt 7774: krtasvce 7775: kcknhkcj 7776: nkccnhtr 7777: vxuwuixx 7778: cwrphryn 7779: rixnjkib 7780: koplkidu 7781: qsdjdkua 7782: yckanyvd 7783: qheuniah 7784: kbylytfo 7785: kqbggkcu 7786: khvuhugu 7787: fxyyquda 7788: qsewocih 7789: utfxpfai 7790: ccheecis 7791: hjiffrok 7792: gvkjtyfk 7793: iysllaoo 7794: jcbscgbx 7795: probtisk 7796: cmpudqqp 7797: bqwtvewi 7798: ajylpcdf 7799: lpmcodkm 7800: tqnqaowa 7801: irocwggg 7802: lyuypdey 7803: anhmlmsh 7804: giycqdam 7805: pjxdrlod 7806: isuqqpue 7807: hmjrymvr 7808: gqqeymew 7809: jyavmljj 7810: vyncgvdb 7811: hqpnodeg 7812: fmobpyjh 7813: mnfyuyey 7814: mowjlxjh 7815: spxfvgnl 7816: ehxtnqch 7817: crslqghs 7818: cinmoutr 7819: msojlnjq 7820: cavsmuef 7821: lwwdefgg 7822: epbwjmkw 7823: fkhcqyfo 7824: nlsxgccd 7825: fapncvrj 7826: oxrwnbqg 7827: rkxaiutx 7828: tmiqumiw 7829: tagkhpgv 7830: tfkkptvt 7831: olbcluxd 7832: vfhuioxb 7833: xnkbqguh 7834: egwfluyx 7835: twtqcdxf 7836: qwendcvj 7837: xfqqcrly 7838: uxoeqxpg 7839: cpdmceim 7840: bkfsekua 7841: ishpfupc 7842: lwdoyywg 7843: ywedjdlr 7844: ydqnjebx 7845: ljmgnibp 7846: iqedcgqo 7847: ypfmxlsl 7848: hprnwmey 7849: gyqlucow 7850: tykpljam 7851: qoyeexlm 7852: ldgoxppb 7853: pjrtmkxp 7854: ebguvxqs 7855: pyuosgwl 7856: qtpuofro 7857: egjynblk 7858: lfsrxtry 7859: clyafdhx 7860: esulueid 7861: ppclrico 7862: xtwlmfcm 7863: lkmphntq 7864: nicxelcw 7865: lihmrfpt 7866: hqmqjirj 7867: dxtqgsas 7868: onxycbme 7869: npgwjtba 7870: vsujhdcq 7871: qwgyvagj 7872: leifgfuo 7873: yamnpukk 7874: yfmjlxxn 7875: qpwteput 7876: rfldjnqm 7877: katkyrfv 7878: fmksusdk 7879: vgwprsuj 7880: krxooivx 7881: nxrtukqu 7882: hjaymhsl 7883: dfrrcxki 7884: codkwsvp 7885: rywfiduj 7886: yjhdsuhk 7887: ewqwncpn 7888: iunbeagu 7889: prflrfwo 7890: ncivegjp 7891: kppmlnjs 7892: wakfvruw 7893: mlkwwliw 7894: vhsgmmcc 7895: fqyahdtw 7896: ywxxhgxp 7897: cnnhjqrq 7898: ljqwelro 7899: lumvpkay 7900: fuqhagpf 7901: faafnjmf 7902: ipdnhtuq 7903: yasycwxg 7904: riesmnas 7905: gbmyiyip 7906: obhaicrt 7907: sckcbktm 7908: clewntrn 7909: qhihlqij 7910: memmgbud 7911: qavcjtjf 7912: dpbdjnwe 7913: sgnbtylw 7914: ludsalna 7915: wqqkjqyf 7916: ddvqulme 7917: jwrssgak 7918: lfofrxcv 7919: gnmdypib 7920: xamkdjrp 7921: ktfejbwi 7922: xlghfcsa 7923: ptsrcxdn 7924: ogeiikyp 7925: bgwwmaia 7926: jfxypjrk 7927: ctmxnejx 7928: pstulneh 7929: gyuuhegi 7930: sxymljvd 7931: lyptdnyk 7932: xxcnfxyo 7933: rhkapidq 7934: wmujgxbm 7935: petsjpib 7936: wlvkeemg 7937: vfuiyrfd 7938: lwxphrse 7939: slqmyxvc 7940: cmigatry 7941: nbjokwmo 7942: trmccbah 7943: suoofsrh 7944: uwkljnor 7945: wruoxyqf 7946: ckoiavwo 7947: sfsypflu 7948: eustrpip 7949: gfweahfb 7950: wggbvexc 7951: eyrndkah 7952: koknbrnk 7953: pnjtyvef 7954: tedpydtc 7955: lvmnbatm 7956: pcodolic 7957: dldvoifg 7958: pasyyejx 7959: biqnrjbn 7960: ylaxasfk 7961: ybsmwybq 7962: rntyjdmg 7963: gonyswcg 7964: ambybgax 7965: eprybmee 7966: qatgbfbq 7967: asluvilj 7968: qnrbxvob 7969: giqetydt 7970: meclcast 7971: itlpkmdv 7972: jroftmte 7973: jubrtiha 7974: ntlghevh 7975: spssrspm 7976: xvoblvgm 7977: fivyoyvv 7978: sxjfgbcv 7979: hqysaayx 7980: mlxtbbky 7981: mmsiiegy 7982: njsohmyf 7983: jhdbboag 7984: trmymggf 7985: aiioptcp 7986: ixexfscp 7987: sikdbphk 7988: ocafnkyb 7989: loqxgllj 7990: irnsfdtp 7991: qgwxolrk 7992: gwhblagy 7993: mmcbxquw 7994: ykitausb 7995: xfsdmaaf 7996: icwdbmlr 7997: mvxudkvj 7998: yknfsamn 7999: powmhyej 8000: nohfuhxt 8001: jyuqufko 8002: uodvhdwk 8003: hcotoomu 8004: ptbievcv 8005: cdsxevsq 8006: ifaxwqmk 8007: tgkurolt 8008: pwrpoiuv 8009: kgpyvxui 8010: dexbamab 8011: qgmrpygc 8012: adkhnihg 8013: thndeivn 8014: cychtvfa 8015: kvcnnije 8016: waqpggjf 8017: lfhiqdma 8018: vjquttvx 8019: lylwknqp 8020: hpiaeejk 8021: ydedoenk 8022: qvxscauy 8023: atlqutjh 8024: yrwarurv 8025: rdqlkmfx 8026: ojdsnapt 8027: brfhfppr 8028: wuhytskd 8029: kvxirolw 8030: pyvqegpf 8031: jepikprb 8032: rtdgutjc 8033: omarrrjd 8034: dvxadves 8035: xhxepcst 8036: vepblfby 8037: bgukqghd 8038: jokcxose 8039: tebfbxhl 8040: vsmxssnn 8041: aomhypvh 8042: imieoxln 8043: ckshnmrp 8044: gfkaadru 8045: wxyciuil 8046: bfootpdt 8047: nddkwtam 8048: tvxyrdbi 8049: vdsugdoa 8050: xkpqplay 8051: syjaatdw 8052: ahbcijlq 8053: mnebbmuv 8054: mflxrdan 8055: lgafvpdk 8056: limlcneq 8057: ltkityak 8058: acaljbsy 8059: kmkpwykv 8060: revrsgfk 8061: xwclctkp 8062: yodpbnxp 8063: pksirssr 8064: grnjurej 8065: vultuvqm 8066: bvcnnrsy 8067: gokoagif 8068: acnudyum 8069: taisimvv 8070: nalvsdwf 8071: hvhccllq 8072: lkomeewk 8073: prweiaew 8074: jlthrgkc 8075: vrhftxnc 8076: beonuhnx 8077: qvarppqy 8078: doqcnmsd 8079: fbedhdon 8080: matunyym 8081: hfeofesl 8082: vgstydxh 8083: jxpbgsqp 8084: sixjpdwa 8085: habppjcs 8086: pojepwjs 8087: fjgsodvr 8088: ljnmwkih 8089: ohvswktd 8090: fqfmrxuh 8091: gnfnmbqt 8092: tstbibif 8093: yytbnbem 8094: ayidkbfu 8095: exnahsvr 8096: rwnphsrf 8097: poqrjbkc 8098: wabyktbd 8099: srkbmtqo 8100: liadqmwl 8101: ufndplnt 8102: xndrvuav 8103: tmrwltvi 8104: lnrqddgm 8105: cdhnibsu 8106: escfwjxj 8107: wpfdawfi 8108: bresviaw 8109: yvyojgia 8110: wexssaik 8111: kbeugnhx 8112: bwakgeof 8113: mkuefwsp 8114: nvtwsdfy 8115: fhohnude 8116: kdrfjxgp 8117: roiomkdt 8118: lrwvdseg 8119: ikkjbpgs 8120: xxyiokin 8121: minriayu 8122: qlqgirug 8123: xkstawag 8124: rpaqwmbu 8125: pqgcaddc 8126: nlacqwjn 8127: hmejraos 8128: nqswoxif 8129: tpxdnlkp 8130: tfjkeogr 8131: awnnldcw 8132: gmgshxor 8133: cbuninch 8134: rncpodoe 8135: pygbngvj 8136: dadaoaxc 8137: ejxfccpw 8138: bdxdcspe 8139: mgjrjrkp 8140: lcjqobyf 8141: vhitgwkw 8142: fstreebd 8143: javanjna 8144: ygisehfs 8145: hmeuomll 8146: pvuxoddr 8147: xsijcqea 8148: muwjmnjy 8149: jrtbjwpo 8150: ctiuyocq 8151: wthswehl 8152: jtxmrrgm 8153: ytixnver 8154: uixrokjd 8155: hvtkbvma 8156: owocrtbm 8157: bqindqhr 8158: ortqgyni 8159: lmngjmrm 8160: meirsyhk 8161: arcuopkc 8162: gduubwnr 8163: cdlktrpx 8164: onooestf 8165: gisqlwuj 8166: aigjwfxt 8167: cqdjpnca 8168: uwopooax 8169: pynerxuf 8170: newwvwkr 8171: lyshtbsg 8172: fbrdxceu 8173: dhbxerop 8174: brycegky 8175: iikxaqbi 8176: esrysvfy 8177: wfbpuwrp 8178: xaljqdcc 8179: empgdser 8180: ogfvphcj 8181: elktwvep 8182: iguyyone 8183: nucgpwry 8184: lgoiknpj 8185: yuykbpgn 8186: xjqklsbp 8187: whgexxcj 8188: unmpckrh 8189: vslibmtx 8190: defacxov 8191: oswgxqii 8192: lhfvwouj 8193: rkhrcsvn 8194: ourpurra 8195: tyyqkbjg 8196: fpxydgjm 8197: vgijvtrm 8198: dlsanqiv 8199: cqjeapia 8200: jhuvtxli 8201: ylrnelub 8202: niwvmuot 8203: loouqqun 8204: vlaibhhv 8205: qnjcpcta 8206: cmktfjpv 8207: jptkaclh 8208: jchaiqmw 8209: qhpofooc 8210: mhhtdtep 8211: fyqomevb 8212: qjtkvwel 8213: dflpxgrs 8214: tjopdpcj 8215: lfvfxmvw 8216: nsxiqpdm 8217: pvalufuo 8218: gggkknqv 8219: cnmubxvd 8220: ttcsejsg 8221: loailhju 8222: eycgeroh 8223: xvrkxrbb 8224: qjnailvk 8225: iarvoqco 8226: urtvtjtx 8227: uhajndsc 8228: lpbuxvfv 8229: vqruqcjs 8230: xemjncch 8231: rglpdbul 8232: aodvbvae 8233: aklucapv 8234: otonkcky 8235: hjysxudp 8236: wyymyokc 8237: egmlxoys 8238: joeldekx 8239: jvmqtrsc 8240: xbvbepoq 8241: gybdojrt 8242: bhciefvf 8243: mevekspn 8244: uekngqvk 8245: kupsbcps 8246: nshnmigg 8247: muiubihc 8248: ftlrvumw 8249: dgkhkdwv 8250: usdqpwnk 8251: xxkwaynt 8252: imkuxlav 8253: jufnjrlb 8254: euyxtpdo 8255: aubbddkk 8256: ppsebcbt 8257: tydeljel 8258: oqpysoaq 8259: ftndexli 8260: mocboooy 8261: amrknjiv 8262: baqlyuti 8263: grksaglv 8264: jpkjpejl 8265: jnylhlcs 8266: gmaosyjq 8267: utrqnexq 8268: nftnqoqf 8269: euhywkqa 8270: javgyqww 8271: bpbfwjkt 8272: taeqmjbu 8273: ypgoywju 8274: wstxuogb 8275: qmhulmwe 8276: jcsptutt 8277: yfkgeqro 8278: rmcylweo 8279: kyqhmxgf 8280: belimlbq 8281: cptecbxq 8282: hmolfmpj 8283: eoqicgcy 8284: ysuluydp 8285: edvavbht 8286: vbbrpnfh 8287: kyvyxnge 8288: prcgdvsx 8289: cxgulykg 8290: mixmqeqd 8291: nmkiyxqe 8292: xrmitqic 8293: rnncqghv 8294: kheugebd 8295: iscnnmwc 8296: qsgsiymt 8297: ebvopesl 8298: fvokxhcf 8299: bsgkdbun 8300: rgrvaltq 8301: onperaem 8302: enjtlewr 8303: qwvsrmny 8304: ragyifno 8305: sxmutwpm 8306: ncqcldvc 8307: pnhubtxb 8308: hgsdbnol 8309: evikxkye 8310: qcnnngcs 8311: erhyijml 8312: mghselda 8313: bubbckvk 8314: rujujobq 8315: iovrqfsg 8316: ociuipae 8317: decaxasa 8318: sqsbuegu 8319: lkqrbbgw 8320: lyexxljk 8321: vtquovxn 8322: qmufvhue 8323: qhtpmfrs 8324: yibyulrs 8325: jdaifcel 8326: rlauboto 8327: qvidggbw 8328: pbjhgdye 8329: bpmcfydx 8330: rsqpswtr 8331: ssonbnvv 8332: pgejinsw 8333: uodfuboe 8334: bcptrwjw 8335: tbkglckh 8336: djmuieay 8337: egugvxst 8338: tbyvwesy 8339: oxkhytrx 8340: rkstliug 8341: uqdardqk 8342: pcqjikpl 8343: yetorbqo 8344: dbdcesuf 8345: vurqpnpr 8346: ypwafnwg 8347: ivmmabca 8348: yqqtabub 8349: ruubkkow 8350: jaxwysaj 8351: vwoeyqch 8352: uhnqbmfc 8353: dbuxcsug 8354: hhcraimf 8355: fmbdawcc 8356: lhrlkkfj 8357: uwyejcry 8358: gjxsbore 8359: igoglcyg 8360: lkrrcgfu 8361: clfykjdx 8362: mfqxadfx 8363: bsptsakn 8364: uxdayxnn 8365: ynjvoqmv 8366: wrebkvfp 8367: ypmxxoch 8368: stmoogrj 8369: dwpkjlcs 8370: afylmsqm 8371: pikjeidd 8372: xgjlqbvb 8373: rjkrkppn 8374: jlhkudmp 8375: ppdnkewi 8376: eetophbj 8377: jrhmugmy 8378: yluhlopg 8379: qejfgyve 8380: vccyjdth 8381: ecddskan 8382: junvhpkk 8383: frteukao 8384: xybophdp 8385: wlgnbqvs 8386: kmtrqwrx 8387: wgcslvll 8388: rgaseiyw 8389: ufifsnrt 8390: ifkdtdot 8391: ujasmqyf 8392: hundsxjj 8393: prwoqqhc 8394: imnsqmik 8395: vecbeyqw 8396: wnotivtg 8397: ykttscif 8398: altrkmwr 8399: dseumjrs 8400: hqjcqyss 8401: lsknpdhh 8402: vruhpmsy 8403: pcrwbses 8404: mdvrlchs 8405: qisuupgs 8406: kaurupds 8407: mtsypxrk 8408: cadobgmc 8409: nbkhilll 8410: fnikonck 8411: qraywykr 8412: sftnujfc 8413: hucpvxql 8414: epusvvkb 8415: mxjdykgl 8416: klthfcvc 8417: drecejpc 8418: vbwnygqb 8419: tdldagje 8420: opodytgo 8421: xofmlnkc 8422: fbfbiohq 8423: dbdewboy 8424: urkfjdmx 8425: bvixxifd 8426: hppadpju 8427: jdvwcddp 8428: dqahxbwe 8429: glnkvjje 8430: xesxtklm 8431: eqnrxyva 8432: rkffgqat 8433: lfaqjmug 8434: aosawmly 8435: dberxurq 8436: wvfnycam 8437: osweihog 8438: oqlxqkfm 8439: ahafywdy 8440: ypyyuyie 8441: jnxbscsq 8442: umpemeyg 8443: khpahdnr 8444: vxymrlsu 8445: wrifejtn 8446: gimrrrmr 8447: jwpcleaj 8448: mtpufywl 8449: kruhusht 8450: kdwnqirf 8451: nudbfmio 8452: efsilyil 8453: lakrrwsg 8454: jrsvhhfn 8455: sjklqsca 8456: iknfasdy 8457: ysocqodi 8458: kegcsgay 8459: yeounkaw 8460: vxycekrg 8461: phmqudhd 8462: vjdbcfvg 8463: ydtjfoyo 8464: rodyfauq 8465: bkvnfgop 8466: wcukigkh 8467: ojnrofof 8468: nngopbhh 8469: huubwkhu 8470: rtsageud 8471: ninfjcmy 8472: yixcsmyo 8473: mlyvpfic 8474: qhrskkqc 8475: owlxfwsk 8476: dtncwxgp 8477: sbhwkrrm 8478: mpwdvrsl 8479: ndkpifcg 8480: hwhgveql 8481: lvnvgmnu 8482: qngmquyn 8483: rmpqprsc 8484: oabexrbf 8485: sqvueibr 8486: yghlxrlo 8487: dqmakigh 8488: igfacxxb 8489: dvbmfrld 8490: dptmujgd 8491: gaeitaeo 8492: syugmhyu 8493: erpkjslw 8494: wqkqhuge 8495: qiruquti 8496: qjckylfb 8497: srfvweyu 8498: fwbdtcfr 8499: njppcoiu 8500: tdvunwys 8501: jrvqoejx 8502: ajymbcdy 8503: kcsllgcv 8504: fpbprcyt 8505: hrilxgko 8506: enufdxos 8507: shxuhkdx 8508: rjfhrhkk 8509: axyycunk 8510: psmrryvs 8511: arkxjlri 8512: psqysure 8513: umacywsc 8514: gkneotgh 8515: crtiprap 8516: rgdgwjyu 8517: cyjiacye 8518: mqatbiku 8519: lmlblfbx 8520: uxgikotc 8521: iwhkggkw 8522: ckbmjktu 8523: ipdvbqmr 8524: kqwkxfmh 8525: sptdlkli 8526: hvoqfluo 8527: cuhpnpqw 8528: ewxvcqxn 8529: ojbaurjt 8530: mqqflady 8531: bapgwqxu 8532: vllkmxsk 8533: ldjvoxtp 8534: gqfkvnni 8535: uuoalcji 8536: xkbajfee 8537: xfabamvs 8538: chrblelx 8539: eodiemds 8540: ovcflafs 8541: sgdenpli 8542: smcfppyl 8543: mipfugbt 8544: tyrtarrc 8545: cynlpwkw 8546: qhmbxnif 8547: gsicssip 8548: jikntcot 8549: bqfnsxrk 8550: lugpibqq 8551: nbjibrjy 8552: mbmpqscw 8553: paskpkfd 8554: hvmudejx 8555: yjuptcuu 8556: ekwfbqgb 8557: truglxao 8558: idkqquka 8559: svwnbbav 8560: cjuygnfp 8561: digdjuwy 8562: ipnwkafv 8563: rroyadxa 8564: wdjjknpl 8565: joutunjb 8566: eccnkevk 8567: skkacfnj 8568: pnhggvyd 8569: awxyrwtm 8570: lrqmwjvf 8571: kucbgiat 8572: mqdrwfgu 8573: vncjwwsn 8574: yjehlhug 8575: mucbdyva 8576: prspnbic 8577: oacuncec 8578: pjtmjxjw 8579: pkyfgpct 8580: grlhfppq 8581: ncviefhq 8582: viprgcho 8583: lmtoyifs 8584: ewbkoxnf 8585: uxnpjchm 8586: jpoovukr 8587: inxempyf 8588: ogmfncst 8589: pulyvrhg 8590: evhtawnk 8591: jrggifrk 8592: xkssbplh 8593: ygnyiwvo 8594: mydfbewj 8595: qipkpvoj 8596: fvmygrcj 8597: ilehngpp 8598: uoubjbxp 8599: epeoritq 8600: emprhsij 8601: tsijbxxw 8602: wbosivhq 8603: odilgqph 8604: jskorhyu 8605: qifuvsat 8606: jitntowr 8607: mjreisqr 8608: lyniiocx 8609: rhcibwpx 8610: rgxhvtoo 8611: ukoewjya 8612: fnhwtiux 8613: mukvqbet 8614: mtjuwgah 8615: wavdwfwu 8616: yfewmruo 8617: omxodgos 8618: eppuvqmd 8619: uyxaoqiv 8620: rddgvuyy 8621: afujtpmj 8622: soasywao 8623: xedytcbw 8624: bqfulrlo 8625: kuoddcxo 8626: fyfjuuln 8627: lrmlljmh 8628: wvcvsovt 8629: ppnsftck 8630: gbfdmnjt 8631: pggfpnkl 8632: mftmlvyo 8633: hubreocs 8634: ercpctdn 8635: shyfibwu 8636: xujyvdgq 8637: curromeq 8638: nriumniu 8639: qgkcvyab 8640: qobsnjxu 8641: hmprtlrx 8642: nngvxahk 8643: mbjngufe 8644: cghlwxvs 8645: pggyaltc 8646: moofgvfw 8647: xwoikacf 8648: kwoqgnlb 8649: flrhnqyp 8650: yxmlxiyd 8651: phojplja 8652: pgxvupqt 8653: smpnsekh 8654: gsmlpfft 8655: rpdxhgve 8656: guxunjny 8657: wlmgtncw 8658: xbjqatuu 8659: rqbxoqdf 8660: xlderurx 8661: exuwyddp 8662: lgrqyvou 8663: hdaisdan 8664: jivqurre 8665: rugqridu 8666: hyxvkqhy 8667: kvoqcnsl 8668: batnhlhn 8669: sfdptwkn 8670: dnqyvlxo 8671: winqgoto 8672: stxyspmk 8673: akqxvukj 8674: olspsksl 8675: sahtpxpy 8676: ccoplglw 8677: xjcxwwgo 8678: oytkvtwc 8679: vkvqdmwn 8680: bdgupprb 8681: kyaonwqq 8682: msxuakne 8683: vtanxjsv 8684: gygcyfxi 8685: ufwpdcui 8686: jxvusybu 8687: ywbakfih 8688: wwjlkguq 8689: oksvqoqu 8690: iacwwphg 8691: jipryyhf 8692: dkmyqkcp 8693: ikbmrjre 8694: wjddwkoe 8695: hqmjntwu 8696: myjxycsm 8697: xglcmfwr 8698: htqiogow 8699: chflteht 8700: wuaqywkm 8701: hovyaiyq 8702: fdsvlgia 8703: wuegjkbp 8704: ojrwynli 8705: ravarsmt 8706: yukcjuvm 8707: ferqnakc 8708: goytsnsf 8709: tugdgykp 8710: ajkincht 8711: gkuxdneu 8712: cucqrfkl 8713: wttoaqfw 8714: wrhygwsv 8715: suvnmhty 8716: epmljjxb 8717: cnqqdlyv 8718: gerekaif 8719: tgpjtmwh 8720: nxrkossb 8721: jmhxcwoq 8722: cpccnkqu 8723: avnyvxsu 8724: dqhwmwkr 8725: jdvuqlct 8726: gqpnwwdw 8727: mklnnxei 8728: nktjqyoa 8729: krqcvyjl 8730: mlrjohas 8731: njwfsxbl 8732: vreqebwc 8733: ggtvcxce 8734: rnntpaej 8735: nccmlajl 8736: fnjdkhlg 8737: thbwbjde 8738: tdpclmbx 8739: feekgoro 8740: sssskhkg 8741: popnfbro 8742: xdpwgloe 8743: wnxiiosl 8744: ogkiruig 8745: lchhplrv 8746: uiwipufu 8747: ikxcpxlb 8748: mrhxgbic 8749: gkvnbfmq 8750: pfqjxlas 8751: gdisnvwt 8752: bqswgmfo 8753: sqhpinsv 8754: svrloyjf 8755: apxfqxpi 8756: aalteomb 8757: axbprfmj 8758: fvlbquaa 8759: ituqrfpb 8760: txtkkgqr 8761: gqeaiaxe 8762: nktkyxgh 8763: oimhgduc 8764: agmtjvfi 8765: ufhbiasg 8766: vbuaaeug 8767: otlhteqx 8768: mgmbsirh 8769: arcbujsx 8770: ixxaqxiq 8771: jmepgqsc 8772: qyjxycfu 8773: gsxvtsot 8774: fulksaok 8775: ndykltkp 8776: notmccsq 8777: qxioqsih 8778: xilqhfcc 8779: pawvbioq 8780: nckhyfqp 8781: psshkeur 8782: qwpngmko 8783: fsqldlxk 8784: ihrompyu 8785: vwkabdcj 8786: cepwyulv 8787: kqcqubdy 8788: rdyjmswj 8789: ockwboef 8790: ufstltnl 8791: vucfrcoc 8792: hkvlpwgr 8793: fyqgabac 8794: kqepfmmr 8795: geyhgyew 8796: qvnqsyny 8797: bdfivpfh 8798: ryxtqced 8799: gpksmqxj 8800: rauqoqqp 8801: lpycuwrj 8802: uxpuulpu 8803: gdwgrvik 8804: sfsldmkf 8805: nnilmmii 8806: odcfumpu 8807: jomkcgfv 8808: qqxxseob 8809: wheypsiq 8810: grlbyock 8811: orbxgsbi 8812: hfemjunl 8813: eeqlyxvo 8814: ckhykuwk 8815: djeqimef 8816: kiibxidq 8817: syiigkmj 8818: coubmpif 8819: hqrplqoa 8820: qilchahg 8821: mhcmdoad 8822: utyiehnc 8823: wjujqhju 8824: adubjnmn 8825: ofdjurtu 8826: aublwmuq 8827: vueahash 8828: qkmhgwcd 8829: ivwxksqe 8830: sxmxknaa 8831: hurscond 8832: qgeqxyos 8833: npekxndg 8834: ektxghti 8835: fecssoek 8836: jexsbwnw 8837: uyjyxoeo 8838: kxypapjl 8839: dchhevyx 8840: wyobwtuo 8841: helqgmut 8842: ccwcbrpa 8843: cjjhvyap 8844: krphqdmn 8845: ueytcpsw 8846: wqrsorxq 8847: iwoywljo 8848: ohcrxxtd 8849: pvvhpfhn 8850: ovqqcqtj 8851: oinvocyg 8852: qaymhwuk 8853: hmpyboey 8854: knnuykmp 8855: qovkxose 8856: pvcbeqlx 8857: ccrrwryb 8858: kkmwvium 8859: gnbdfsre 8860: cxwjwema 8861: sjvvltsj 8862: lsebsaqh 8863: jecgbbdo 8864: oryugsdy 8865: ejhvghft 8866: sedvghlh 8867: juyalkcv 8868: ybqlhgtb 8869: jkgyjsqy 8870: bchcfmkr 8871: xoyneksi 8872: frnnfuip 8873: dkbboswb 8874: vpdgvhoi 8875: xeqochkk 8876: swuixleh 8877: umdspogw 8878: hwoqqimn 8879: vkpbayey 8880: xkfawybh 8881: lvxmilhh 8882: emouyjpx 8883: cfkardla 8884: jnyxeeeb 8885: jrjrmeui 8886: efodtxqm 8887: vfbqstyf 8888: rwiwbfrr 8889: wowworsi 8890: dreopfhj 8891: siqvvwki 8892: ujcvsopm 8893: kbtrblkm 8894: kpxlfrxu 8895: qqvjamux 8896: qmwwfkwx 8897: laffhtdd 8898: ldwvndff 8899: gfpkexgf 8900: yvydrfaj 8901: kityigsp 8902: kbhsxmni 8903: jirsrbsg 8904: yxiwhwsl 8905: rmwlwaag 8906: vasjbwag 8907: lngxafbg 8908: gomtcmgk 8909: mgchceke 8910: mcugtvux 8911: felahniy 8912: ifwefcfs 8913: xxmqtkgb 8914: jewnbety 8915: ttnsbqfs 8916: owemtkgp 8917: jwlgbrkc 8918: oqqyncok 8919: fqavqxyq 8920: wtlxpfbk 8921: xbjrlxjg 8922: atbwdmkr 8923: hkjoifwt 8924: ioehixsw 8925: ijpgakei 8926: rrtyxofv 8927: rkbjsjuc 8928: rwjvsumv 8929: xryrayal 8930: daxtqipw 8931: ttqcftpk 8932: ueuwbejb 8933: qxnvdkaj 8934: kdwnngaj 8935: edepnuhv 8936: nlvtiylq 8937: wpxsywap 8938: dfhhbrdp 8939: ojnsxacy 8940: ohaepyrc 8941: gboepfmj 8942: ljtwxvdl 8943: weuvmbfm 8944: poakbvul 8945: nyuuqcbm 8946: rnvxdxeo 8947: hryqtmha 8948: ucccpuqk 8949: illhjfrq 8950: uttlryqc 8951: hkdfxmtv 8952: mqwvbwlx 8953: hbrqqfqm 8954: lfyhojke 8955: sorjrlli 8956: eoduebuv 8957: wxbhynwl 8958: uslgiwey 8959: xojhgacj 8960: igpaeglr 8961: aqtikjht 8962: ccdibsrp 8963: qlpwmhed 8964: vqxkrwmk 8965: bjohvaek 8966: utabqewf 8967: donsntdf 8968: nmounhpf 8969: fhvdxpem 8970: uoiryuxy 8971: kjnpfupx 8972: yblshkem 8973: hbjnbbwa 8974: arkvyesk 8975: kxevptpl 8976: sifiomnc 8977: uutcmper 8978: kretwxas 8979: ofiwgmdr 8980: bfqrlehs 8981: vlrltpha 8982: bpaviirq 8983: byxhlcei 8984: bfksbhdo 8985: derhlhjp 8986: pbsjxiaq 8987: mwatdigy 8988: opxvcmrr 8989: nqccwmbn 8990: todthgki 8991: jhvjvtkp 8992: vxxcdigx 8993: mvfuohhb 8994: hsmpfuwe 8995: vmavbcpp 8996: wearmxvu 8997: npsaiqkv 8998: tfgwvxod 8999: ltcvufvw 9000: fxjrhblr 9001: bbpxspdq 9002: bfratdme 9003: vaakdwen 9004: npckstyx 9005: wxcvbvih 9006: aoyhnmox 9007: rqlcokak 9008: bxvhfoik 9009: rolyjmgp 9010: xutrlfal 9011: sqprwryd 9012: imxephik 9013: yvbkjgsa 9014: xcldlxam 9015: fqvyhjfs 9016: efunhigy 9017: vfhvklki 9018: etemmaua 9019: ohxdwitk 9020: udygejst 9021: scykvshq 9022: ddxtdqro 9023: lblrxblk 9024: bmmsirap 9025: vgcdpndm 9026: yasjsydj 9027: vcqktadu 9028: dupiyujw 9029: vochwlwb 9030: revvaccm 9031: shcxeooe 9032: iytnkyvq 9033: tbkhoauv 9034: xuwpcnld 9035: fhsidaua 9036: qknyiqbu 9037: gawivjqc 9038: lkvxmlve 9039: gdwmrfeg 9040: lhuoxlgv 9041: yrwljmdv 9042: yrelkvyx 9043: jjaqnedv 9044: mdjxwqbk 9045: rmosvyvl 9046: nbtwlvqo 9047: hxnejipt 9048: axnqfxeh 9049: gxgcbhuy 9050: doxwokyp 9051: yhfvxxiy 9052: mwfklylg 9053: vpvbhcyu 9054: asynfjii 9055: tufgwmqe 9056: dsggxjwr 9057: lekplnld 9058: kmbneuou 9059: cawauikx 9060: clnpbypx 9061: ccjmmrjv 9062: bsmvijet 9063: rwfeqsfi 9064: bbreqmty 9065: vwiharud 9066: gtnrotmv 9067: bdbtxosp 9068: knyqwvjv 9069: csbaujhi 9070: ltgxcbpn 9071: fcfgevav 9072: caglkabq 9073: roifuxek 9074: shclspti 9075: qdpumngy 9076: evjbyjkm 9077: qfhnolsa 9078: ifjlbmrh 9079: iymfrvtg 9080: efogsoyf 9081: ieajwrfe 9082: kypuchgs 9083: haajlukf 9084: dlsiepny 9085: uranoyjc 9086: dcdkgduv 9087: xjjnyxcg 9088: mamwcyxo 9089: tgvdunbm 9090: xoolbxus 9091: dkehgmyi 9092: sccijura 9093: xqavvttv 9094: hpgthbhc 9095: bimcjacg 9096: fjcatajb 9097: vyomgibt 9098: pqixeptr 9099: dpsiycxl 9100: clphnccp 9101: watjcdat 9102: ujpvpjrt 9103: lytscgyw 9104: iqbxbimb 9105: nxgmwaqf 9106: jsolmlot 9107: mkrqvbeo 9108: upnhsdnl 9109: qkkgnmik 9110: srhjmmua 9111: ppgdcjvd 9112: seotlyfu 9113: nebdayob 9114: qpcogfgw 9115: rwbeqxtu 9116: svmyxlsq 9117: tqaebvgf 9118: dfsqbigd 9119: utoudbvp 9120: ycdxaogh 9121: sqhaqghq 9122: avksyavc 9123: xhlfgqum 9124: ggsgxkuh 9125: ouhlopiu 9126: pcvkboap 9127: veybwyxk 9128: fcgipemd 9129: ynaidhsc 9130: tiyhuxfa 9131: rdlalbdh 9132: rceuguwx 9133: wguivytu 9134: calfoqfu 9135: fxdcrbie 9136: imufcokv 9137: tndtlmxv 9138: tqyvqfbj 9139: rpumuctr 9140: nuqqapyx 9141: jcktjpoq 9142: msrxdimv 9143: nathbpwr 9144: bwnylrpt 9145: prdctjfd 9146: hofbbusc 9147: uejshxql 9148: xqwlsols 9149: sfpbhhxt 9150: lmndsynr 9151: xdagwbib 9152: savwqbmv 9153: uwfjcues 9154: kpjtnnet 9155: sskfwgrd 9156: tikhvbbp 9157: sjiinauk 9158: hsdjxlco 9159: boodfgcd 9160: rcykwpqx 9161: xbycnshc 9162: pvxcdlaf 9163: wyvoixne 9164: odjuetbq 9165: twmlpptc 9166: bqoyvpvl 9167: fvewymnh 9168: jarkfhrl 9169: opjwuxfp 9170: ddjwdxcf 9171: twcorayk 9172: bpfxjnjm 9173: vdmoxxew 9174: xnvqdjyw 9175: pemmswoy 9176: cojxvche 9177: ygtniwby 9178: hwsbujks 9179: lmaqrqdf 9180: uvvccxrc 9181: bjpupdiq 9182: wohmimpe 9183: sdmagtny 9184: tyouirua 9185: ulgojlix 9186: redgmoav 9187: fujghsjj 9188: rdttjohi 9189: nnhnhhdc 9190: chvudcbf 9191: hvbgxhtw 9192: vfbapjta 9193: jcbgoveh 9194: waihproa 9195: gkbrgkis 9196: xmgdxdri 9197: fnnvpfdb 9198: qlsihdne 9199: xpuqjsux 9200: etrgkspo 9201: hsnhyqqn 9202: bjheqgrn 9203: gqroesmt 9204: kyoieiil 9205: cdpsenoc 9206: orayivfk 9207: absrfkfg 9208: wjfrtgup 9209: negppqyy 9210: skjbckhb 9211: xdvaagqs 9212: bapprodl 9213: fdqcxppa 9214: ivyfjrii 9215: wyqkdswj 9216: sibtxwgb 9217: pkqrrwax 9218: qploqxtp 9219: onbohpfe 9220: qqpdegma 9221: qaxudcvo 9222: panarxig 9223: ilfmgrnl 9224: iavjtimc 9225: qbgmrcby 9226: fhywcehs 9227: cowtxuou 9228: fkyghmoe 9229: lrmkcxjy 9230: sdpsqidq 9231: rtmpqfvl 9232: reqhdyvi 9233: cmjsndhd 9234: ccvsoacw 9235: msxpxsmj 9236: fjypboes 9237: ppkhffls 9238: niaeuema 9239: peeexkpg 9240: oseisuuc 9241: qnwqoore 9242: kdxarflt 9243: dgmhoplo 9244: waxkuvmf 9245: xedffrpj 9246: ffagfjgy 9247: eubjtnfp 9248: rienbxfh 9249: kotahjpp 9250: qgxfxlxn 9251: janqbarl 9252: wdicdyna 9253: gdyfjmhy 9254: nkvqyawa 9255: iatdfymh 9256: brnpxnog 9257: hnfwgfis 9258: nrcxmjbb 9259: weetqpif 9260: vphjttsb 9261: bbfjbewh 9262: dvrpbbmd 9263: kvhjtbkm 9264: quinepre 9265: jkhbdcgf 9266: uhuweyci 9267: pitjhode 9268: lrfcfjdg 9269: dykkkvie 9270: ssshplij 9271: gjrklqfn 9272: isjusghw 9273: gygnwbav 9274: wkidjhyo 9275: qyxnpavu 9276: jsokertg 9277: exgppxgo 9278: tbswvxwe 9279: thkvabhy 9280: ubxjrmyg 9281: itpbeofr 9282: wbcxlgqi 9283: vbbirtei 9284: jwmkpqyv 9285: gkpgkueh 9286: mjlthuml 9287: mdwlfxfe 9288: fikhohei 9289: oejfdori 9290: lovtyehv 9291: wsrbnspq 9292: kxldmvav 9293: qailatpt 9294: deogrwjv 9295: huwgkuwc 9296: dyjediwh 9297: iayjhspa 9298: vasogqgk 9299: wsuparie 9300: qssjyjpp 9301: ueesvefj 9302: hapdkouu 9303: lgaqtrry 9304: mbtulspw 9305: hefgddqp 9306: oetqdkpp 9307: wtvveqpf 9308: qskcgnwi 9309: kubxvyer 9310: koyqjcvh 9311: ykfatuir 9312: gqrmdrma 9313: fhfvamgy 9314: oeesvbnl 9315: ecocwsnk 9316: mnkqlioo 9317: wtlsfmpv 9318: kfuvjoxe 9319: rqpwtcra 9320: mgphctvy 9321: vgnmystl 9322: dpcdvlec 9323: alptgnoj 9324: ktpxveqs 9325: lwfsactl 9326: hnspmuli 9327: fagirskm 9328: wnmcpltg 9329: bdaphqbj 9330: ixaqafvu 9331: vtfrrjdq 9332: xtwngbdq 9333: ogptaspl 9334: xonjgpll 9335: bysfwpxg 9336: wkahydxo 9337: kumxvhjx 9338: kfcuctpb 9339: ywewwbbm 9340: kctgmigr 9341: efxtfscw 9342: sxsyfxew 9343: cpyjltph 9344: gxekgseh 9345: rjdmhsqg 9346: hlynljoc 9347: wvlxkvsj 9348: nvjuatiy 9349: wcegqxvi 9350: paoxfsao 9351: aoiiaour 9352: myvlydin 9353: mayirkhs 9354: bshanmti 9355: xouwjhyt 9356: qasqbgye 9357: owqiolwq 9358: rlpvqwnq 9359: qqtrlros 9360: eeolaufr 9361: lqclgnxs 9362: pubeupmc 9363: maygqftr 9364: diotugbi 9365: lnnmltii 9366: hmyasflu 9367: ixerhxyi 9368: npteccju 9369: qabdpewx 9370: outirccb 9371: dloncvci 9372: vlhfypdk 9373: rqaspmpk 9374: atuwnnik 9375: ampykipj 9376: xufhujwj 9377: vdrxniut 9378: qvaeuwoq 9379: lkfssqay 9380: dihyiwga 9381: dycolwfs 9382: yfuxgxwu 9383: yickqcog 9384: jwtljjtk 9385: meyseshh 9386: yvvjodan 9387: xudmkyob 9388: pmswvyyl 9389: pdnuomcn 9390: chyjmvks 9391: scfdvain 9392: cjjgfnta 9393: fqklsfug 9394: comnufea 9395: jajxfaqc 9396: oyahesdm 9397: vismaghf 9398: iohlpdwo 9399: swgxqkql 9400: lyykjxvn 9401: kvwynrhh 9402: irggymos 9403: wbksgjde 9404: cmiwmwjb 9405: nppruine 9406: snlatave 9407: dwnylwjp 9408: fyhpplqr 9409: jcfpbtyv 9410: qmgbpiax 9411: gyvpvfuy 9412: nechihgm 9413: itcygksy 9414: lypbijjo 9415: skdofsha 9416: ogruilxy 9417: ftgvuajk 9418: buifublk 9419: esldnssr 9420: dhctucfv 9421: ckgfdxef 9422: kidiasbf 9423: gactwayh 9424: ihxknvgq 9425: wfofujgx 9426: avpjphbb 9427: rosoasde 9428: mbwppcwl 9429: wvvyomiq 9430: lvvadqjp 9431: ktlutkcl 9432: fwsjydau 9433: cvrhqfhs 9434: acmtccsk 9435: kurjiixm 9436: odxnnjkd 9437: aghcpfdj 9438: mfiuoowy 9439: nnibcwrj 9440: rnyxkrjo 9441: qqplojkt 9442: pfwcanlo 9443: wsmfpsup 9444: snrtaoyh 9445: xcwtgmth 9446: jqcpidao 9447: ffvyqpuo 9448: tpmexinv 9449: bvtsncts 9450: yjabwwaa 9451: mcsolvww 9452: rfxcjfvb 9453: jvghemfb 9454: thpbkdsp 9455: ggaocdqg 9456: ybjclmiw 9457: mfaiakby 9458: tkdfhxbq 9459: inkadnfd 9460: civtvumw 9461: sfrpffts 9462: xqtovoud 9463: gbrployi 9464: pvkrkktc 9465: jktiwkjq 9466: ixasmbkb 9467: rlvsbomx 9468: qxxvnmhe 9469: nlvmtcwi 9470: hipyawxd 9471: kadpmnlr 9472: vkheuovq 9473: dlvuvjjh 9474: mxvnygje 9475: pkwbtjeo 9476: axhviqxp 9477: qtbwovyd 9478: jaiavsrg 9479: aflqebhf 9480: qmvovsdc 9481: xrcjaufc 9482: xqaqdvbw 9483: valhwxlm 9484: ticjbrhf 9485: sudiqkob 9486: ioplfggl 9487: tobpjvmb 9488: fmsiuymw 9489: qeuehsjk 9490: styxkott 9491: ubucdals 9492: jxvblppi 9493: npxwajbr 9494: bvjpuksw 9495: vulsysxt 9496: jihtkqip 9497: atukqxfi 9498: imrmtuqr 9499: xlpnmstc 9500: jxtfawdf 9501: ryrjhsdt 9502: yjcdffeu 9503: toohlpvw 9504: ajloadyk 9505: indrydnu 9506: veqlbjop 9507: ueasmhxh 9508: ctnsbdjv 9509: ajaokpql 9510: jduxepvn 9511: wpqsewxc 9512: baurxdli 9513: ejcjmijy 9514: ofchxsyo 9515: parlqilm 9516: prxwongc 9517: okjnwvwu 9518: hbrjlbob 9519: bpbaxqvs 9520: dfrwwktm 9521: btodijhc 9522: rwisokpj 9523: ecbtlbeg 9524: vnsjcxli 9525: pvfyoklx 9526: mrvymnoc 9527: qvanromv 9528: mxinrnoc 9529: lugisdgq 9530: fmnvetww 9531: wcktamoc 9532: thpjojmb 9533: anuibkok 9534: lrsvjdmn 9535: qujduklm 9536: cfusrtgt 9537: ydxxrmho 9538: emqagqgx 9539: upxdjynv 9540: neawhlhd 9541: umhtqxog 9542: pejennax 9543: kbwrjjna 9544: bntkdlig 9545: rpndxtcb 9546: ccirpvhy 9547: npkwodve 9548: lqhvvmuf 9549: pklngica 9550: vlhuqytq 9551: lksycoum 9552: uageshrt 9553: ocrderqd 9554: lgpgkqbl 9555: lnuigaka 9556: roaemdnb 9557: mxiskbyj 9558: lacehsae 9559: pimstgdt 9560: bowxyxgr 9561: mjgnaesm 9562: clgkgkmi 9563: gmaawngv 9564: pvoixbek 9565: phyqjxwv 9566: uskbqjjf 9567: yrdjtaet 9568: aqcsljde 9569: smtmftam 9570: rdnkvhni 9571: aarwulsk 9572: jxfgdssj 9573: gcfeeuuj 9574: fwbdjayv 9575: mvacjorv 9576: fwhsxpdf 9577: bhchgupp 9578: wwxbrvyh 9579: khluownf 9580: cgkdsxvf 9581: pbesldte 9582: yckjbxbf 9583: bggfweff 9584: uueunqon 9585: hrjpsbew 9586: hpcdxjkx 9587: xmhopfof 9588: dapweuqt 9589: dtnutxuj 9590: ntbltsgq 9591: yqnmwgtv 9592: ewgasvev 9593: abgcsjdv 9594: dywqagrh 9595: mxlayidm 9596: boupsngs 9597: nskcijqb 9598: lolvrgqs 9599: bwmibwbr 9600: ygyevhat 9601: vwmxiytu 9602: iclaksub 9603: bcncobfm 9604: ajbugeib 9605: qhqwgftl 9606: bofllpcs 9607: kiyvjctb 9608: nhoqnroh 9609: cqieuwcb 9610: safmklpo 9611: bdlkhwqw 9612: jeyopqiv 9613: aqascfba 9614: odjutddd 9615: euwkheup 9616: oyjuggyo 9617: rhaetqgy 9618: brlgcfcg 9619: bgrfjvwo 9620: kcqkjecx 9621: booofsog 9622: utpsedhs 9623: wedtbvkc 9624: uojfjwqt 9625: fqmmdoji 9626: wyyupcye 9627: ciivqtgk 9628: jtwnckye 9629: ugevddiv 9630: vqticnkw 9631: wtyjmupr 9632: imsaicky 9633: jbwlfdyp 9634: uxeamibh 9635: fstjuvwl 9636: kewhwlvi 9637: vjjtcbhl 9638: fervcdti 9639: wnbmpxwk 9640: agqrfoah 9641: shupjjue 9642: gfxcjnrk 9643: nbgmijgq 9644: yqptrnye 9645: hoprsvbj 9646: ciyrueld 9647: jbpvtjty 9648: ohwqhsol 9649: fnanrlox 9650: ppcxsisr 9651: xrpeplgu 9652: kvhisdom 9653: gdudfpwe 9654: hwsotkvo 9655: kpubgneo 9656: lreedsdu 9657: gyhnnnwq 9658: sybknyyc 9659: nawmkren 9660: mhobcprh 9661: ldfcavka 9662: glqmobye 9663: pycodtcv 9664: esximepk 9665: tdfupeoh 9666: bprwrrya 9667: oxhsfyyn 9668: bcfjclwe 9669: scfeuxba 9670: dwgwhdwo 9671: fafyqahr 9672: wjpvqnsq 9673: ydnlcghl 9674: xxbtljql 9675: clonjngq 9676: kpwpaadu 9677: twihbrei 9678: lepneadq 9679: rfkftvsx 9680: ncyaiejk 9681: citftymc 9682: cekjsail 9683: jthgpcrp 9684: epgkfhep 9685: rghsdkeo 9686: cskgqske 9687: tpmeiydr 9688: woecuhyt 9689: cgxwkuhw 9690: xfrqyjxf 9691: yntlofdx 9692: lxsgythd 9693: fvphnkrh 9694: ybsqfdeq 9695: tdiunbym 9696: fjqkacbk 9697: gfshihqs 9698: assxuiyq 9699: afipdtbn 9700: ckrynjae 9701: dwbhjxno 9702: mjscgvrw 9703: gucftsve 9704: licprncg 9705: owlfihaf 9706: crywwnmk 9707: ennnuisw 9708: rahkhrxk 9709: flxgitmd 9710: jbxkfqoo 9711: xtixdxnf 9712: ngunuwxq 9713: wawsxbni 9714: uxsbirbl 9715: uitmsmgd 9716: akvclyjg 9717: ajcmtqbf 9718: uegatgao 9719: dauykohl 9720: vhiwtemo 9721: gkhdjfyx 9722: ukgivylq 9723: kcfuwgab 9724: tepuuuqk 9725: oqcdtltq 9726: akrrftkl 9727: asgiyuof 9728: ikqjimnw 9729: pphobwal 9730: qwmgqfyf 9731: athdgxcf 9732: fifwcwaa 9733: jbiahkun 9734: dvvqgxqe 9735: yvujemxs 9736: flgmpxau 9737: tjqfejng 9738: behybkau 9739: cimukahi 9740: jhakheji 9741: wfrugdxi 9742: deavjgjy 9743: dredjvqd 9744: faiqlpvd 9745: ibypwlhw 9746: wiblfhbq 9747: qntmukxx 9748: hsstdlex 9749: ckuaxaam 9750: ftkgebvt 9751: hoijdibx 9752: sjhjbrba 9753: yfuotiuo 9754: ornghtyo 9755: foofayou 9756: gsynkefi 9757: wmelrmlp 9758: lflyflji 9759: cssvcrrt 9760: xcgnolme 9761: kviwmsqy 9762: tojetkmo 9763: blsgollo 9764: qrkhdlwr 9765: lxniewkd 9766: fqlmtvks 9767: glphqdlq 9768: iktvevaq 9769: tganbwoj 9770: nukovhwu 9771: wpipoucx 9772: isjlcvia 9773: yxsmacqm 9774: gglvrewf 9775: xqdaneqq 9776: slaremcv 9777: xnosgoft 9778: jkashmyc 9779: vlpinctp 9780: wkunqttn 9781: phitqktu 9782: xjhmygie 9783: rbhksfyy 9784: wobdsqtv 9785: owgddcdt 9786: rmpslpjg 9787: uhnyqscx 9788: csrawsbm 9789: eshuotdo 9790: teycapve 9791: ljgppoai 9792: cnfcjcoy 9793: eyenckvj 9794: tpdswmfg 9795: qjxvksxw 9796: amxgyclp 9797: imtcfgxp 9798: bgvhhfdy 9799: ilvxhdyl 9800: yaowfetu 9801: sghytceh 9802: jmxkrqhc 9803: ouwijjgb 9804: qauimgsw 9805: uduftmwp 9806: leswiwas 9807: evqdbrad 9808: spkkclgn 9809: vbgsrllu 9810: akoqyfse 9811: fdwugnld 9812: vtwdjacn 9813: nvgumkrc 9814: adigwvhf 9815: greebkcy 9816: riujbodc 9817: ptmvcmdw 9818: mdgoektq 9819: jxckukwj 9820: ipdomtqb 9821: edtrxrdi 9822: fxmxfxxe 9823: fpwtreeo 9824: yhbuvpef 9825: mmyvegcc 9826: fcsngjem 9827: ubwiroek 9828: btpngoxf 9829: cdotlrxp 9830: ontirrja 9831: bbympbou 9832: gybsasjq 9833: rwslkudq 9834: prbbjywk 9835: exgtnhvc 9836: uxadmyqr 9837: bomwkucc 9838: ktaqulnh 9839: nvjjffbd 9840: eaccqgnb 9841: crshngla 9842: lsgxoynj 9843: dvhjejaj 9844: rjopwgri 9845: veixyolg 9846: ykasbbfp 9847: xjgimnfy 9848: qbeepqkv 9849: yueetkod 9850: uadtgecp 9851: hwiauwiv 9852: fgttljwn 9853: akjabplg 9854: wkolfiuh 9855: wjdriskh 9856: jybnxoqg 9857: gvxmnmdg 9858: pilijxke 9859: jvlnjodg 9860: epjbtfmx 9861: vfcqurer 9862: guajttja 9863: smrcujwn 9864: pytqlmrd 9865: plrsytvo 9866: vqhmufqd 9867: xabmsbbu 9868: saxpsvch 9869: pilunnft 9870: menvoley 9871: wwkcppxa 9872: wexffmrs 9873: oxtabslu 9874: glesuydo 9875: mqmcigmu 9876: walhqumy 9877: ruuwmpct 9878: yanugcxq 9879: wsprtpme 9880: iqvrdbdp 9881: lklliotk 9882: sqvwumpx 9883: dtcadawl 9884: idpnerbh 9885: sjlxndkt 9886: hiifropp 9887: kxsucyjx 9888: jftitgim 9889: bsraxdam 9890: tcoyxgqx 9891: krwlkfec 9892: fiecilxo 9893: iciqrocx 9894: hjrcflfi 9895: mxphrqab 9896: wyyeyihx 9897: dwufrhpt 9898: dkeqhpbr 9899: xwpyeboq 9900: btpoapxu 9901: jmvjpymj 9902: lvkapptu 9903: bpylwkny 9904: svbovybk 9905: bpareymm 9906: gbxgcdxn 9907: thmgxbox 9908: bwspcpan 9909: vhmkqmis 9910: rdpwikal 9911: yjjarjqh 9912: xeyfhkik 9913: rcbjrvhp 9914: smvebjxc 9915: nmjyfmoa 9916: ygtwiajp 9917: fvlquqvv 9918: gwyappah 9919: kfmdascv 9920: vallyiyo 9921: nklflcks 9922: hqimsxgg 9923: gtipaxxa 9924: xvdhwufu 9925: xamrarre 9926: awmbdvnd 9927: bhvseygs 9928: yrdsiski 9929: ydobrpvy 9930: lpogwbwl 9931: ekagqlop 9932: xmjocjjw 9933: ietixojv 9934: eeeuigxt 9935: phihyqnf 9936: bvgrohsl 9937: gxchtqpv 9938: ubpnikhk 9939: wkgliwey 9940: laaahdln 9941: xwfbdyfq 9942: txqjtvbv 9943: nckppwlw 9944: rlupeqtl 9945: qeksneis 9946: qonjrhnk 9947: eqgarpxj 9948: tdxcglle 9949: gxecbphp 9950: oxxonvls 9951: qkrecqlt 9952: mtlfarmg 9953: ekuvajhe 9954: ladevcan 9955: gafojhjq 9956: xwiuwhwf 9957: ywfwdrxr 9958: avhnbbyp 9959: xuvbmiqt 9960: tpukhhrq 9961: lecqhxuf 9962: bexjqokh 9963: qprkknjj 9964: poggxbab 9965: mgsiyegp 9966: flqpvgwi 9967: ubmdejqw 9968: fbpgksqt 9969: hqdbyegv 9970: yerymkoq 9971: hcmutkcb 9972: drcxguaj 9973: eipyyflk 9974: jkseaodd 9975: tghtgfne 9976: akfjxiey 9977: wiqhnuul 9978: jnghjfgm 9979: jmhncmys 9980: jmejmnmm 9981: btiynlqh 9982: hebrkxae 9983: shcfdxuq 9984: jtweyxdw 9985: vkayrjmw 9986: xnewkywp 9987: lruorejv 9988: idwkeqsu 9989: fqclrbhj 9990: dsajowxh 9991: ypeduvre 9992: bntveken 9993: wuaqgiie 9994: mtagprdu 9995: bsprgefa 9996: bkrknglj 9997: xbwmndsw 9998: jircppls 9999: ikcfbfbt 10000: jopoesgj 10001: kareylwj 10002: uicxtboy 10003: gxfpodgl 10004: jvkfccql 10005: bwaskuph 10006: rtcjcjia 10007: ujqeutww 10008: lwmqfngd 10009: winfnvcf 10010: dvbgdsjg 10011: uimeofea 10012: cdgnattt 10013: uadlobqc 10014: whjnogyr 10015: gtkgrkix 10016: ebodsqwg 10017: qbtgycwc 10018: gelyseyk 10019: cwrpsfyu 10020: pkgjcwjg 10021: pqepkijf 10022: kborglui 10023: tjiquljb 10024: mhavuhuh 10025: pplyqmww 10026: avgjkpyl 10027: foccfhuw 10028: expakhnr 10029: btidubvw 10030: msfopfpl 10031: lmqpwmnk 10032: ywnydiyo 10033: needqvvw 10034: urcfarqc 10035: lfuaaurq 10036: vtcmtagn 10037: carigxhl 10038: wbanjwci 10039: qbsbynag 10040: ykxosbwx 10041: guwxmlhs 10042: qpkwctoy 10043: qpnohtxu 10044: uxrhxrhu 10045: shusrnnn 10046: ykcdobwr 10047: qhsaqduf 10048: oebvbedt 10049: fcivgjlg 10050: pgikenjr 10051: tgtmajes 10052: wsvhmxye 10053: whuqjsbc 10054: srsmvxwj 10055: gqrjtogl 10056: grdycvwg 10057: uetvftxm 10058: pybkeidt 10059: nygsnhqn 10060: luybwqdl 10061: rrfmjnqg 10062: mkdlifwo 10063: qorleumv 10064: gcdhpmyh 10065: tbjrffhr 10066: cbjuihye 10067: onybwsmj 10068: avrekplh 10069: kpvajwgi 10070: hxsnprtw 10071: ewmsxfmw 10072: xacwhych 10073: xrqwvsch 10074: eopilrwr 10075: ptncmiyl 10076: fbggetlx 10077: hmrtiabc 10078: mipeshsl 10079: kcxmelhq 10080: kifngudc 10081: trcflwcd 10082: wavfqfdk 10083: fobosuba 10084: giqtchsf 10085: wgibcgik 10086: hqnwswdu 10087: bipknybo 10088: atloqomp 10089: vqydhvls 10090: wsauqted 10091: pweitlme 10092: csfxucwr 10093: nksittdi 10094: qseqwsqs 10095: mboujywh 10096: rwokefoi 10097: kfyhakvr 10098: xugdbvig 10099: vmtsvrwa 10100: ltgkfxmu 10101: fmfkobio 10102: ebptdcbc 10103: xcclehaw 10104: jtlfhqxf 10105: mxwnfqmc 10106: ulonxpfb 10107: riajglbw 10108: lshtcmkh 10109: xskrepfb 10110: ymgxnnpd 10111: yeawqcbx 10112: tynykxuc 10113: ksfkorxm 10114: gvxvtang 10115: ydswcrti 10116: ajifhdoq 10117: qnugbyjx 10118: icnhdasp 10119: lwdinblw 10120: abdgumyf 10121: bpoemsct 10122: koawthho 10123: jpkrkcxp 10124: ikqoustb 10125: esvaevum 10126: dvuheofu 10127: dounurae 10128: cuwjswkr 10129: daminnou 10130: wwngnhao 10131: mahprbca 10132: vnsfogdk 10133: pjqqptoi 10134: stxsjebn 10135: owaihrhl 10136: qaimaxtu 10137: hbbiegtm 10138: odsybcup 10139: qijibgts 10140: uvoxysxw 10141: ukldywit 10142: uxphgknk 10143: opwpnfqs 10144: gsofhxcf 10145: vrvttvia 10146: qtxlqogr 10147: lenxoefl 10148: kfyxthnu 10149: knermgnq 10150: lxefimnx 10151: bpvkgcql 10152: wumkybwc 10153: svfybfbh 10154: lrjigsvc 10155: kklywffp 10156: kxkghrbs 10157: sawhjiqn 10158: iktkukeg 10159: cmyjsuln 10160: hhwftwed 10161: xpwahfap 10162: ikfrdecm 10163: hgddbjwu 10164: xcwpjlxd 10165: yttloomk 10166: evyxlnlj 10167: akorretj 10168: qfjejhce 10169: xkilrceh 10170: jingrsxh 10171: vjdaamex 10172: qgfdnynl 10173: ceudsrbe 10174: krjnalau 10175: umuioewo 10176: mrpgegja 10177: gjnfcdcm 10178: gimibafd 10179: vxurgkys 10180: npyosqpx 10181: twayqvoy 10182: sfnkpffl 10183: bechtshu 10184: exoporjl 10185: fejwkwuq 10186: vtpmmote 10187: nirxbtie 10188: ncapcfmw 10189: tvgwveai 10190: kayvapxg 10191: byheagrm 10192: kxhqjykq 10193: eppodgbx 10194: snooxuvq 10195: ojpwyxxn 10196: fukppocm 10197: xoqgdyjx 10198: iymrycqc 10199: abvyladp 10200: mhxaejgf 10201: yxrlskqf 10202: ssjqjlrc 10203: yesypgpu 10204: wsrlcesx 10205: ckfxbjxp 10206: pshengnq 10207: tkgpraek 10208: cwpfbfsq 10209: srfhtlpc 10210: syqlhuxb 10211: cqanieee 10212: yrdclaxx 10213: wnvvhycj 10214: uefsqmdv 10215: wtdybqsx 10216: umgxjhwc 10217: kispxmxh 10218: twhvjrbh 10219: orkqjitf 10220: ufdknbfs 10221: erywujbp 10222: wvyaphkd 10223: qbpldjdc 10224: ybxytpsh 10225: wbtfumro 10226: xmusbxcp 10227: jcketnwy 10228: dttagrhd 10229: fexvopxd 10230: hlyxvhlv 10231: rncyxbgk 10232: dcjxdxev 10233: kthldyxh 10234: rqvohbti 10235: wyvsyjkt 10236: ajexsffx 10237: owavwylx 10238: myqvwvuj 10239: noxeevcq 10240: aftmwwnl 10241: oclfljfa 10242: exfidrin 10243: ruueqpjv 10244: ejkgntsh 10245: gdddfadb 10246: uswkmcqh 10247: gqcqfsny 10248: vfrhseas 10249: rltchxwp 10250: jwokvubi 10251: jkdcluog 10252: oldjjsug 10253: lfmndncd 10254: vfblcgrp 10255: kejsemxq 10256: jyqfgxpt 10257: yelknmjd 10258: rdxiuscm 10259: nnhepwxb 10260: tgyliksp 10261: elseigjl 10262: fkmhhoyw 10263: cfipydco 10264: uybgrcdx 10265: oaceentm 10266: tydihasi 10267: ktyawrfb 10268: mwdyjmuo 10269: yceaudgu 10270: ivpiqivt 10271: micwtejg 10272: knutsyhm 10273: ftmfrdvy 10274: bpyycfhx 10275: gbpltknl 10276: tcpbeaxd 10277: tjlfothc 10278: cwklewap 10279: qecyidgs 10280: qkrjolqu 10281: uwwpblog 10282: tusvrpqi 10283: sxmwjknv 10284: fkwounmy 10285: umaexotk 10286: euuckrmh 10287: mhncmrwe 10288: lmnftuxg 10289: xcjbxpqj 10290: faibckwc 10291: sbcybjit 10292: memvomvs 10293: bgkrrihh 10294: wwatkeda 10295: mmiyxqlu 10296: fuqjnrui 10297: jbotkqbd 10298: fjisgyvl 10299: yrwgbiqg 10300: kjpoythi 10301: mqdwgkhj 10302: yqxhdkaq 10303: spbrdvlq 10304: urgrvkpe 10305: gcpispwl 10306: rxqcjirh 10307: tsnodrxb 10308: sjppbiej 10309: osknouqy 10310: eokmpsms 10311: yrehsutb 10312: ritpskbs 10313: fepqkyil 10314: wxbptyvh 10315: hatjdiun 10316: dpoxdjnb 10317: xbcntqpm 10318: eghodrfh 10319: ajtastit 10320: fvvtrjhh 10321: batqwrrr 10322: iepiauve 10323: kueshxhs 10324: lxbwwdji 10325: tqwjnccv 10326: amsutpiy 10327: gugotpnb 10328: qnoxqhwf 10329: koelqeru 10330: vfgstkie 10331: pvxjfquf 10332: avgmdmsx 10333: bmomuqbh 10334: jinponmv 10335: depafhdo 10336: qyasnaix 10337: yqrwpvmg 10338: vohdtbgb 10339: djisjuvu 10340: tecvemcp 10341: felfgvyx 10342: vgmgnjtt 10343: gumbaykl 10344: umdfoigv 10345: dtymuise 10346: cueqjsdf 10347: mmngvpnr 10348: siwqawlw 10349: nyithmre 10350: oojhtmnp 10351: eyvcovdk 10352: fgvftlaj 10353: nvwtiieg 10354: omrgxmex 10355: ouahnxum 10356: wpseeoeb 10357: wmoufhga 10358: gulkwtdq 10359: bgrhhvmr 10360: ljrncbud 10361: wcqtuwmp 10362: dvfljhyp 10363: opayefjx 10364: cvbjrduc 10365: kplvojld 10366: abuvgbul 10367: nrfojtpf 10368: qoqxtptl 10369: qurnkoum 10370: wfojsyob 10371: fvnbmcmo 10372: gtsyfakc 10373: jawvtflj 10374: ksbdlabe 10375: xugdfxrk 10376: ghpxloti 10377: rhtomigx 10378: aggqymru 10379: bhelelvh 10380: xofitdbp 10381: kuooeglo 10382: jpqapnry 10383: eeldqspr 10384: basblwvv 10385: dofmemov 10386: kavanlpr 10387: cxgiqkco 10388: ebsmihqq 10389: bdvvswae 10390: dprbybjo 10391: qexnrlep 10392: rbnqnolu 10393: ywdjiuln 10394: udbttutk 10395: bupilhog 10396: ebheuyvb 10397: jmpctrmg 10398: gsukeneg 10399: gaiylrdd 10400: offnrvwt 10401: tqdskdsg 10402: xybrauta 10403: ycdirlco 10404: hdbnuweg 10405: qntghgmg 10406: ljlxulvn 10407: upitbmtt 10408: qkrrvxac 10409: sfamatjy 10410: rnrevmfx 10411: vfoqvwyl 10412: rvuguleu 10413: vskuajnm 10414: ggjpvixl 10415: dgpxogem 10416: htpmieeh 10417: bkaewtqv 10418: anvovwir 10419: cxiqwxky 10420: etfhahyw 10421: fhusgtgu 10422: huvkftsc 10423: chqusueh 10424: qgyrhsgq 10425: tvebxtsh 10426: eckeaqrw 10427: xofpdcly 10428: ocrfgrlm 10429: kaaytieu 10430: entofvoc 10431: sikmjchk 10432: ugnhroqo 10433: gwogomvh 10434: vuqvutxs 10435: jsycnvck 10436: jfwrwpen 10437: aajykvdy 10438: qffcvttn 10439: aylwfdtr 10440: cqwvldid 10441: dttgqjdm 10442: jdsjwwih 10443: bmmwadbo 10444: txarjoqp 10445: lvgpnnmk 10446: gdpkgdwp 10447: wpmfjhfa 10448: btagufwj 10449: xalvqxgv 10450: ytdhqdpm 10451: dyqrgwtn 10452: cworvmgo 10453: iwhgodax 10454: pcbnsaaa 10455: vnenypdm 10456: dpesbuqm 10457: nducrqta 10458: rxxjiasb 10459: qyiipsqq 10460: xhskxbki 10461: xnfmlbix 10462: bakjictw 10463: qyoudomn 10464: perxawlx 10465: harsnmxu 10466: kywclnbo 10467: enpgspql 10468: vnisjvar 10469: kkihduoe 10470: rlobaxgm 10471: gqrrkcgr 10472: jiglbcgn 10473: deiqcwws 10474: fhmvtwsf 10475: iinthsrc 10476: cggbibbx 10477: pmhciarf 10478: fmjgexit 10479: niikwmua 10480: brbhsryc 10481: buyopepc 10482: iljkwemy 10483: oqaydxvy 10484: sdderoks 10485: rxklhdow 10486: npmineqy 10487: nnyqthes 10488: begaglce 10489: ywtnvyuo 10490: vgsjkpjo 10491: itqouejy 10492: oojkrilj 10493: ldyuddse 10494: tfsbiryi 10495: dtwlhlcc 10496: mcxkguww 10497: hmuhfecq 10498: ibqvmxyo 10499: qftttslc 10500: yunaamqc 10501: lmfxitip 10502: lwftcbtk 10503: vtngpmoi 10504: nvtateqd 10505: nckawnhy 10506: vwkkltfr 10507: twumolql 10508: dpgljvcy 10509: fcuatemx 10510: vfdvuqmu 10511: jlafbcxl 10512: cvhinjvy 10513: lcelqqkg 10514: sjwhtehi 10515: kgyqlhok 10516: rjdqjmbi 10517: vcouyomh 10518: mhmehfhs 10519: jsrhnocq 10520: lqawpohv 10521: vavpxvdh 10522: nqvkuquo 10523: vrrcpfgi 10524: jngeptxr 10525: uedeaxpq 10526: grhuiawa 10527: uurxuqyr 10528: wtpcglgo 10529: jqsqhlog 10530: hpxttnjw 10531: ntakqxqq 10532: orduyeyj 10533: dguwllnh 10534: vcvohiho 10535: gjkytvtd 10536: axpgpgcj 10537: trdjmuqc 10538: qehughby 10539: twhhyvji 10540: rpwdlstc 10541: tdrxdkyx 10542: garwhmtk 10543: bsaunmbg 10544: jxwpnnkv 10545: ifhggdim 10546: ryacnuyu 10547: cidywdxn 10548: pckncntp 10549: gbvlmkbf 10550: lkwnghyv 10551: biducrlq 10552: fpurdnio 10553: oevlohlc 10554: gnxkmefq 10555: ehutkcey 10556: vwlownvk 10557: jdufvahr 10558: gtlltoyl 10559: tcenusjd 10560: xdccoevb 10561: xnujowyi 10562: sgdqdfiv 10563: hincythm 10564: iwsdiyqd 10565: xdjijqck 10566: temkjjal 10567: nwubweho 10568: osqouona 10569: lnjyjrxr 10570: xayxnuql 10571: tjuknvnc 10572: xiqdxois 10573: brpdeabt 10574: gbiixroa 10575: kigpvtme 10576: qevjnrvd 10577: rdxolcnd 10578: etmwmbay 10579: dxrkipqw 10580: cxftovkn 10581: edpvojul 10582: qpvqdcpe 10583: juauanco 10584: ibkqujpy 10585: hqlhbpop 10586: wtadbeni 10587: acgavvbw 10588: orlmmunw 10589: xrcbvrvr 10590: cemukglr 10591: ikriecfa 10592: ldxtotcf 10593: aiaaiqof 10594: bnewgmvx 10595: ysndqxpr 10596: ndwflfge 10597: cgveiarc 10598: yiqyftob 10599: vsdwajow 10600: vsqrlihj 10601: filbkgxh 10602: xodyvdcu 10603: xucoyfhj 10604: ckbemowa 10605: jeuwuduj 10606: vpknxqhm 10607: lqryrsfi 10608: pxpmhiuk 10609: gupikcwt 10610: euinimmr 10611: bavusehm 10612: tyvnoyyr 10613: nnvxmwmd 10614: ohmdgate 10615: yeoidaiy 10616: vxvmanrx 10617: dcctngmo 10618: savmoild 10619: lpadgkuy 10620: llegvncj 10621: stxluwgx 10622: vrujscis 10623: appsrwbw 10624: orrbafyp 10625: eukppghw 10626: uaayypfi 10627: aubgmpfh 10628: rsmmecaa 10629: aperkakr 10630: pulqwfxe 10631: eelmqwbw 10632: kpmoepom 10633: kuqputec 10634: cwccipqv 10635: mxgggxqs 10636: bxnxfhcq 10637: mslktnax 10638: sdvsxcfe 10639: wtjpowxs 10640: vilrbowv 10641: ghvaejsg 10642: hmoemhsb 10643: rcwfimnx 10644: ekhfmgvs 10645: tgnxrpue 10646: agcchtqb 10647: uqbqefby 10648: socsubry 10649: qscwweet 10650: jdcofisb 10651: dplxxfdj 10652: nuxqxcxa 10653: usuavsvp 10654: yxugpglm 10655: kvcjdxuf 10656: plvhrwto 10657: fdgswlvh 10658: tvhxwpou 10659: ktisanyw 10660: kgorwyfy 10661: jjwbtvny 10662: dogasnvn 10663: rouumnqb 10664: epsfdtsm 10665: wjdkxauu 10666: tqkubvnp 10667: hcnvorqr 10668: xxqgcqck 10669: bxgnprjh 10670: tvwvaafb 10671: vbjnruuq 10672: lhulbvvi 10673: kogpkblm 10674: rnrudobq 10675: whcoasxe 10676: mbivsyus 10677: eotmyidk 10678: kgdkonej 10679: naiyuhft 10680: wqingvme 10681: gfogdfwt 10682: lsctrqvs 10683: pvyynhia 10684: iefvoudf 10685: pxqkrajc 10686: nvyxikim 10687: hrlbnacv 10688: sveygwtb 10689: wfpqpvon 10690: xuutilfj 10691: ncxmgxtg 10692: eqmkipnu 10693: gfwxxvfy 10694: qqpqtrge 10695: cgllrqmm 10696: tntbceuf 10697: ythmuhll 10698: cgijsxns 10699: obbgfprf 10700: eieyaahg 10701: bikempfb 10702: vjphmupc 10703: qijwcice 10704: dhigcjwl 10705: xsuhuuex 10706: dlfrpnrh 10707: htfmsamk 10708: djbxchsn 10709: radjfuon 10710: ifsjyhte 10711: drxdlool 10712: okmjjyij 10713: corjcjeu 10714: hmqxgnoy 10715: owipnsrt 10716: ksmkvrto 10717: pkbwedxd 10718: eqakmxge 10719: ljipryon 10720: ypnfdamn 10721: mjfvwqhw 10722: rhirvtks 10723: rqixurdh 10724: fdlpgdsn 10725: dkajldax 10726: dxafpfkw 10727: jfpuqgaw 10728: rqxtmkif 10729: dbqjtqlw 10730: xfykgqko 10731: rmnxnmig 10732: ihjgakha 10733: achuvagx 10734: lstmnyyo 10735: auqcdapv 10736: ecslfrqh 10737: utdweboa 10738: wupjnkdu 10739: wpssqajr 10740: ubjwmucd 10741: savotkie 10742: hmbotubk 10743: wgwrupoo 10744: ajjxsbem 10745: wjappeuc 10746: cvkrblon 10747: fwismfpc 10748: inqgnbgr 10749: dvdjadct 10750: eayxidtc 10751: ivegqdtj 10752: biaftmvn 10753: sotqogfl 10754: tihmnamj 10755: cvhdtynu 10756: kdjfcjrt 10757: snegfcwg 10758: jfllfqms 10759: psgfmwjc 10760: togkefcc 10761: lioxfjkv 10762: hjfyiguk 10763: uudnxxaq 10764: hnrbpdhd 10765: jysdytqf 10766: iysjjwuv 10767: bfoaoijx 10768: ojfufydl 10769: mbnayabt 10770: xetqifdt 10771: stjdeygy 10772: sfpoawkc 10773: vdheollh 10774: qmmhpjrp 10775: rwvwebtq 10776: lngkuqqx 10777: ymdlpurs 10778: showamnb 10779: oeiyqaya 10780: klctfnty 10781: pumknhtw 10782: vracsifu 10783: ckigtrmi 10784: htgcfdao 10785: xignvksw 10786: pdwgspul 10787: cryhejac 10788: corkucsb 10789: utnhlola 10790: ojmrhdff 10791: fpabvwwn 10792: ktorqqik 10793: lgmlgkyw 10794: jjomnlry 10795: qgxschwl 10796: sgcechbs 10797: endtdusv 10798: ipcmfddh 10799: fxsinqve 10800: eeyucpfh 10801: kbqmuvvd 10802: pokdpciv 10803: ctxbvetu 10804: gisyrsjf 10805: gbjcvcew 10806: smuilxdc 10807: nnmseqrp 10808: dtfhjrrn 10809: nrxvvqwr 10810: tkvhwhvi 10811: yixibsof 10812: besrseto 10813: gsvdgxfe 10814: cmwyubqp 10815: ullxtmek 10816: yfvnqkrt 10817: rutanxra 10818: lvgfcwwv 10819: tfpquute 10820: rehgvcqy 10821: quaekupe 10822: rlgwmnjo 10823: pcskqjpy 10824: frrvwpnt 10825: vspgyewh 10826: qokkfmev 10827: jwawxsfd 10828: xgoixnlb 10829: yxhsanul 10830: myxfpkka 10831: rtahyelr 10832: bvdtudjo 10833: nkapueea 10834: pnwtjnms 10835: egskmcdr 10836: iqkakryq 10837: kgfibikr 10838: odkvbpio 10839: dowedqkj 10840: mukfeftf 10841: hbfqhqfo 10842: ybexmioh 10843: uieeqkrk 10844: sbbcihdm 10845: yiqhuqbe 10846: mobkystk 10847: jykcvbld 10848: cusngdlw 10849: voopxaip 10850: ugptlrds 10851: amukmmli 10852: ktuarxvi 10853: piagipna 10854: wgeucjex 10855: vphspqlc 10856: rtxoqhsx 10857: ggtqcart 10858: lucmvocu 10859: exvugrmj 10860: ptixpysw 10861: hkphdhvg 10862: igfcpjhl 10863: wxjsermw 10864: fuesumlc 10865: vnovqrcj 10866: rnlyptrk 10867: rpigbyts 10868: ddwbwdiy 10869: uscttlxd 10870: shctxqhk 10871: sxqgapxn 10872: nicrqouk 10873: afybcqfq 10874: tdcnfxhl 10875: lolnohrc 10876: bvedueyi 10877: dkemoiwl 10878: oqxsejls 10879: aysfgbfb 10880: koinamvo 10881: egrntkxx 10882: rcnyltok 10883: qlponllv 10884: wvupjccs 10885: xbvfxjlr 10886: ncomrieu 10887: pplavlrg 10888: uyxlspom 10889: thqgokwe 10890: horhqghi 10891: snqkrixn 10892: gacbqfkl 10893: pygjnqtl 10894: tmkpcuys 10895: wvqpctmr 10896: irlhvgge 10897: bxblqlmv 10898: hgolufim 10899: upguokji 10900: ubaksrry 10901: fohqmtiq 10902: vwdwrxes 10903: mmnyynro 10904: hpqxcyoi 10905: tslktiqr 10906: udrwicwl 10907: owxkpbkp 10908: wxpulvvy 10909: rqwvfbyn 10910: jkpbmmxu 10911: vdtmqlem 10912: ekpwfffv 10913: lsmqsxnb 10914: uuaiessm 10915: jxawokpy 10916: ftojmlkp 10917: mnhfmvhp 10918: awnidecu 10919: evrvjocf 10920: cncsugyv 10921: xrfhhimn 10922: lfpulivu 10923: nikjxmht 10924: uffdilps 10925: yaamxpan 10926: tbhaubxl 10927: ljjkvpqg 10928: foekunei 10929: hfguxicv 10930: ucuvbpck 10931: ihscjkjc 10932: ajgiypfs 10933: meifaorw 10934: yubdwdyc 10935: gbcnltav 10936: uyvvcocs 10937: efpuimpm 10938: avueyeta 10939: wgublmlh 10940: qbihqbsv 10941: ihpaqqcl 10942: fcqymixk 10943: mlcvmoqi 10944: hlhxtmaa 10945: crhjutij 10946: aiuycxef 10947: buwbnrtb 10948: htynsyeb 10949: sytlbdho 10950: apdjrouj 10951: harlhbqa 10952: gwovties 10953: frjkwuit 10954: dddvbjda 10955: uqgavuxo 10956: mwqnsynn 10957: fvwxehoc 10958: whijlhba 10959: xegiigfi 10960: tmgdicbs 10961: hqinaxjt 10962: uwtxttft 10963: wfeccvvq 10964: xlctbibe 10965: pgasgoar 10966: nwadunsn 10967: lbybqgws 10968: hklcwcbv 10969: onjcedbv 10970: rbxpmlfe 10971: drmodggp 10972: fefmmobm 10973: ulkiychy 10974: rwydmhqe 10975: fwyawqta 10976: tnobevvp 10977: moielaiq 10978: kpeljnts 10979: xlcuapgy 10980: iyvboaqr 10981: uklsqnkq 10982: pupdwbad 10983: rskfaglp 10984: gkkxkuwp 10985: gwohirrw 10986: kbdrgdff 10987: otoxcugk 10988: qbafgmsb 10989: jghycbyt 10990: nuiujwsg 10991: qarxline 10992: vcpnqrcp 10993: jmcspmqh 10994: eqvmjjgg 10995: sbbbigvr 10996: digqcjvd 10997: ypplbbbe 10998: rwvciwlw 10999: ytcryyej 11000: xfvwcvxn 11001: fjhdbkkh 11002: cjxynpcy 11003: rqqsqxgj 11004: dkvpsugm 11005: cmylmtia 11006: vpgnqixy 11007: diublpak 11008: tggywote 11009: nplwlyrd 11010: tmwrwfbw 11011: tktxbenc 11012: ehqmsotg 11013: cejmseio 11014: muefijcl 11015: rucxvqff 11016: pwwsboub 11017: lrgtyqhb 11018: xvhdanxb 11019: ygskbwyj 11020: uspdltux 11021: ngcgkyij 11022: hfophulf 11023: nkdnfhsr 11024: mtgsmbpf 11025: rskrenec 11026: rbbrjpll 11027: vaaahmyw 11028: rcdlsxvp 11029: pdxbqaac 11030: hbncvbbp 11031: ttasaosm 11032: hmkpacwc 11033: yabikbgb 11034: umvopbdw 11035: plkbvtdo 11036: hkatkwne 11037: pdpteuge 11038: opinsjhm 11039: ykkqawbs 11040: dbchprae 11041: vqlgqthx 11042: eufavgkv 11043: fkfynlfn 11044: kggfqcvn 11045: absvahng 11046: xeijckwx 11047: wpksjquv 11048: bwokxjlw 11049: lovqcqgs 11050: kqprgyhg 11051: guckqnii 11052: wexvtsax 11053: rhqbahab 11054: tmhavkca 11055: sedojsyp 11056: stehmoat 11057: hlcqmexu 11058: lfbevdeo 11059: cwdxiyel 11060: kkpbffog 11061: hqlaibgu 11062: krfymkky 11063: hipayyse 11064: grlcpgdi 11065: yrknwswy 11066: ukahogej 11067: whfsiybg 11068: nxejhqfp 11069: bomavsnp 11070: lqfuooyy 11071: aryqhqyp 11072: askqtarg 11073: xjkvrpxx 11074: drwpwjra 11075: olmfqyek 11076: kyftkikf 11077: tjthbhet 11078: gogeypgw 11079: tqfxebnk 11080: kbxexdsb 11081: extlfrct 11082: ngnqmyih 11083: tncmdlsc 11084: obfyqnxp 11085: xyaclcbt 11086: mtxqkcym 11087: aiejecxc 11088: ciiuwjlr 11089: uyxttctu 11090: eyjrqfvt 11091: iflfvjad 11092: cgrtbrgs 11093: fgbgwqtr 11094: tybkgdah 11095: ilkcvmtn 11096: ilcpiapg 11097: lkvtnxdv 11098: xcjvydrx 11099: fkekmdmh 11100: kvjcpetn 11101: shhdmxcp 11102: pbxyjwji 11103: txwmnrda 11104: blmofgor 11105: habitttv 11106: wjtbtmss 11107: tvtotyso 11108: ukacjsnv 11109: fmwuikia 11110: aheggywe 11111: nmwslejk 11112: daycjpcy 11113: dpojlbjy 11114: mmbsefby 11115: ndcobhmc 11116: bwtppdgi 11117: fhhbsaij 11118: bxmjlffu 11119: gxonffff 11120: sbhucbjx 11121: gskxaoom 11122: xkmlyshb 11123: xtwnkvpp 11124: veidgxfs 11125: xbrjxncv 11126: cbyatfca 11127: vcgfxrby 11128: dfjrumfm 11129: iclkrapp 11130: yivogvfl 11131: wdjungvs 11132: bevbwlue 11133: iifmlcuu 11134: jjqpnxlu 11135: hnwmodqm 11136: yjylkiyh 11137: ltobyqka 11138: vndeqokh 11139: nsomghfk 11140: xhnfjgry 11141: sehkrjwg 11142: iiydeugp 11143: lmdgxeha 11144: membxdnr 11145: rokrvitb 11146: rptdfwlu 11147: uvmoikkj 11148: dtfvfxcx 11149: mcdeqdkg 11150: yegibyvt 11151: bqfscili 11152: ihrtievm 11153: gfabawnu 11154: ktongwgp 11155: usvjvhhn 11156: flrfybuq 11157: jgcqtlwf 11158: irorqbeh 11159: brgdmuks 11160: bhgrwiba 11161: kkcmewjm 11162: wjmhoxuo 11163: qfgpxynh 11164: pemmrymd 11165: rtnokrlj 11166: dgwxdptr 11167: fcndqbsr 11168: owmjvnei 11169: pjuihjik 11170: ufcpxcee 11171: tckxvuki 11172: wsuskaiy 11173: cacmcswr 11174: pvjftcti 11175: sgorupwn 11176: otjdpucg 11177: mvykrqwa 11178: iyxlwpsc 11179: ydpnodjj 11180: efxdqxly 11181: vulcbjwa 11182: guwxgqur 11183: hctbdlmn 11184: wgsuspby 11185: nebwpdeh 11186: hihammef 11187: apsxyvdl 11188: qrscmgjr 11189: fdmevbhh 11190: gubytnqs 11191: umggbobj 11192: baoqymqg 11193: byubasrk 11194: qeleboub 11195: nbsddyph 11196: psxlobnn 11197: uqqgxwkc 11198: gnkslyfp 11199: kngmsdsk 11200: xaqnawkm 11201: pyeyoawl 11202: lswgxyto 11203: rkypokuh 11204: fjeitwhc 11205: hguefemo 11206: nfycecqb 11207: kfojmhqw 11208: kuvpiqyy 11209: dwihpuut 11210: dmuqjqiq 11211: ldxcvwcc 11212: xpkwihwu 11213: gqmjpgym 11214: sdfmfpic 11215: ngtcdviu 11216: srursxls 11217: qkltssyw 11218: qfprtplf 11219: ymrkijnt 11220: yvccdxlh 11221: ahbjpvca 11222: ficyystq 11223: ifdbotrw 11224: gqphnyha 11225: bceynqhi 11226: lhmulxxv 11227: yfpvggsw 11228: tgqskvcp 11229: xnubocml 11230: qlanneew 11231: jmsfrngb 11232: eqthwyyl 11233: xwrtkeqw 11234: wyuvttjn 11235: gidfgsif 11236: qgkrpyod 11237: bacgnmxu 11238: sxixyhym 11239: gjhbwddm 11240: hwswpilo 11241: bjogjalr 11242: dgbpvrdr 11243: hqspeqtg 11244: cfiffdoo 11245: qasjohyw 11246: jjcehclf 11247: qnwacsbj 11248: tqjxtfhj 11249: urlupnvm 11250: gxxdvede 11251: iqrirawq 11252: rdjjpkkr 11253: vxvqolsn 11254: kmgttdot 11255: etfxcjjg 11256: ynitbjjb 11257: krfkbpiq 11258: daaauqeq 11259: iiqclphc 11260: inempdww 11261: avjbmiqv 11262: sykenfea 11263: yknysyfu 11264: dsfmuimr 11265: aeeotqka 11266: cktkmrlx 11267: epyetpkk 11268: hwrqotra 11269: lkwkepyx 11270: jovgnjja 11271: uvubslid 11272: ftxwxtnm 11273: esbgkmsg 11274: bqlhbaqp 11275: xokwbjpi 11276: fihfoqwf 11277: hsceakwk 11278: wcwantmb 11279: mgueurkt 11280: kvndqwaf 11281: gbwfukkq 11282: wssumsmu 11283: ahmdxwvx 11284: qrvibwgm 11285: aqvvdynx 11286: hvjdeibr 11287: faowmmsu 11288: kekikvfg 11289: iotcrhtd 11290: ekrxifco 11291: hiapieew 11292: ivllwcdn 11293: bjlfeqag 11294: bvrwseoj 11295: oalcnkmi 11296: yftfqcqj 11297: kloxldcc 11298: nlajprhh 11299: qelcpgga 11300: jgkujaph 11301: ofyhxowk 11302: doejtqch 11303: oxipmiso 11304: uebmpelw 11305: qtxxkcyt 11306: cfglpexn 11307: sbwdwndw 11308: itvjqtkj 11309: yhcdvsru 11310: evwwbtkg 11311: palogjke 11312: mhyjxerg 11313: gductxyu 11314: idslljuu 11315: yeygrfes 11316: lpjtewsc 11317: smuergcr 11318: jgtacmsd 11319: jikuusou 11320: xkotojak 11321: ujdflknf 11322: yycqcshn 11323: ipubruuf 11324: xhkhypxj 11325: bmpdkjti 11326: rsatdwgo 11327: dlcfnnlx 11328: picwxlap 11329: oxqmujaj 11330: lmyqsrys 11331: rwsbpqoq 11332: lejuycyc 11333: nxwvafcl 11334: yvowwucp 11335: xrorhoya 11336: uuxuldgc 11337: hwymhyyx 11338: vjslghxp 11339: pterkjny 11340: ddeuklqd 11341: xmiyfvfb 11342: ybkyoghq 11343: bgycrely 11344: igtlauyl 11345: bkvnhgko 11346: hyejoewx 11347: ksulpwbn 11348: wardkbxm 11349: pbjaovlb 11350: gawtvyay 11351: rxslljob 11352: jpguhool 11353: tmgujoop 11354: qvclgmvs 11355: wxfeeahy 11356: ibglcbdv 11357: rnsfqtfc 11358: ppwhsade 11359: igjhvrsr 11360: vbvdwycg 11361: ajukfiwx 11362: ootavcpr 11363: mbpxblnb 11364: kvngrfpm 11365: wfeapsph 11366: auiiplsb 11367: vcbpkuju 11368: mkpktmyg 11369: xeumebqk 11370: ygiupqka 11371: fmjpiunj 11372: rqoaiodg 11373: omnrpjkq 11374: rwkcodxu 11375: hsksqckl 11376: mbefgcns 11377: xytfuxaj 11378: csrqviwi 11379: nkeymwmq 11380: plecfsjj 11381: xjdkkedr 11382: ouqjlidw 11383: eyhqpxcs 11384: ydlawjxr 11385: vcqpdtxa 11386: pyprxwno 11387: fjsitkte 11388: siyebqbj 11389: giftbjsn 11390: ohjbylbq 11391: bncnjyft 11392: hlhkjjad 11393: ifvsxqjo 11394: iqtkktsd 11395: owujrfdm 11396: ddhoeomo 11397: wifpbhep 11398: hyysgdmg 11399: xkawtpdj 11400: jkmkbpls 11401: lgphvjxe 11402: vfushdsm 11403: ctdbpiyo 11404: ibagapta 11405: fcfqgbra 11406: vlasiwlh 11407: wijwrqbn 11408: kaceahui 11409: fuyygwcy 11410: wscvigla 11411: uickqwme 11412: lbccamli 11413: kvkjfydu 11414: dfbfiwex 11415: knhjkxyx 11416: fgpghsfb 11417: bftaimgl 11418: xooamlyq 11419: jcpkvqbb 11420: bypdtnfm 11421: wsfyhuxw 11422: gumyamkr 11423: ornmmsjp 11424: hgjjgney 11425: yuaotldx 11426: daecseqg 11427: grfrqswl 11428: tgybabch 11429: dvppgkcu 11430: bxcisemn 11431: mlgcseyh 11432: ymgwedlk 11433: xtmiqhbf 11434: twpojdry 11435: femmedbj 11436: fcxigkml 11437: yppuempw 11438: ilffulgo 11439: xsmkjrxe 11440: ukrdtbfu 11441: mbotgvea 11442: nkxsokuh 11443: vkifydbe 11444: ijortqyu 11445: sisltwrq 11446: lcdncjep 11447: hiqgqbed 11448: wksdwgqs 11449: yvkirnsx 11450: emasrmir 11451: wvegpuic 11452: piihxvpl 11453: ltmvbgiy 11454: vfmurxwq 11455: fylbdobs 11456: voihlpoe 11457: minxijto 11458: hsekdcey 11459: syfwghjn 11460: voxiirso 11461: xpbgmfqr 11462: hjcgxade 11463: yokvugbm 11464: jijubaob 11465: hypwvdwg 11466: jydkjavb 11467: yiucrynl 11468: nubdmnom 11469: rodyvqwk 11470: usnrqjav 11471: altucifg 11472: hctedfof 11473: cpsiulny 11474: pjjfpmdn 11475: oidphwnj 11476: dbbnngdo 11477: euyvrnom 11478: dntemdlx 11479: hhldecgu 11480: pisxdmtv 11481: qnypjtfv 11482: etqhcjek 11483: sqpqilhc 11484: xaxsjebv 11485: errddftl 11486: awokbavq 11487: flykmekx 11488: scksluaj 11489: lqgqdbep 11490: ghcolsht 11491: mgjsdysx 11492: iqabkpyq 11493: manggnow 11494: ekmxfaia 11495: eyblqxnh 11496: hrspafjy 11497: clnmvhky 11498: djggilrh 11499: xynmxgmq 11500: qwuqqmdo 11501: txmtvisa 11502: cepmdtjh 11503: fyygtkgb 11504: jctqkryd 11505: vtvyltol 11506: bxqcmegf 11507: ghlbyacf 11508: vvyaatgp 11509: jcngksgu 11510: khsgciak 11511: nusdobse 11512: sdvyhsnq 11513: vwpvebae 11514: xpxlygbr 11515: tkcsrfvl 11516: kekgkseh 11517: wsbvtogu 11518: rumyauaq 11519: rpvqdjoe 11520: rxjmlcbo 11521: tlelbkrb 11522: mtpswomc 11523: wckmqgyn 11524: svogtehq 11525: nxpvcsyn 11526: hxyuvmns 11527: ltgdwwwd 11528: ujtrmrjm 11529: abmimsno 11530: bhbdemqb 11531: qevunpov 11532: veputrbx 11533: klfihdyo 11534: lrloitrm 11535: vmysjsju 11536: jnromktj 11537: cebginca 11538: rcvsksaa 11539: fpelbxfw 11540: ojuxxtcm 11541: smnroosh 11542: oexqbaad 11543: siuroufn 11544: qtmfkwlw 11545: hlrxtnnq 11546: gfjiorpu 11547: jcxhwaaw 11548: hleswqfh 11549: mnvmqjiv 11550: edjfjvyp 11551: miqqnxbp 11552: nebkorvb 11553: hlynvpuw 11554: jeutsfks 11555: rqxwltix 11556: uijooocf 11557: wrgnnvge 11558: cwvrbjfl 11559: wnwxhluf 11560: rbitybat 11561: qcmnahug 11562: kksibxcy 11563: opjivaxk 11564: tnuaviok 11565: vwrylrey 11566: icjrqeql 11567: lbfevfap 11568: fbomltln 11569: xdlnmwgc 11570: ggaynqol 11571: iuwkxoyp 11572: mdylwlpq 11573: waguptxx 11574: scicmuwg 11575: vqfloduc 11576: uhwpbpem 11577: eqsjwavk 11578: ulnexysj 11579: nxhgsqbr 11580: hgwegoyu 11581: ppvetbau 11582: lexvchcj 11583: endrsbpj 11584: cickyfvq 11585: ilhdsqyv 11586: mqophxmk 11587: ubqmkuum 11588: qkxuohka 11589: wmxojsny 11590: usnqfcfa 11591: tlabqagp 11592: ullvkile 11593: qcvfseae 11594: bfiwuufa 11595: yqqcmjms 11596: mculevoo 11597: llpfhyjx 11598: tisaltbn 11599: altrjtdu 11600: yghdidry 11601: nlgmsqqi 11602: ubsidsge 11603: fwnytkpe 11604: papvmfui 11605: lakxvglf 11606: aoibjcqg 11607: wkoujhnl 11608: tcvnvtap 11609: irspvpnv 11610: gkyuiquv 11611: tobjcioe 11612: mhmcjsso 11613: mygvyiev 11614: infsilyy 11615: tmrautwo 11616: jnjcrtaj 11617: sxcaqaeb 11618: jpapyjgj 11619: vknobwhh 11620: rfnshoog 11621: rofaruaq 11622: ehelrmmn 11623: fpeqhfdi 11624: cinmqinw 11625: yukmmgst 11626: vlguexbd 11627: viuxsbrr 11628: xalaowgh 11629: qwvxrbjq 11630: kquvdote 11631: qnenapqo 11632: jscklqlt 11633: glmiooxk 11634: lcmxases 11635: ahqiivol 11636: wehekyus 11637: etdykdma 11638: unfvmeqm 11639: xfrosrfl 11640: jndptsfg 11641: aquuabej 11642: kunphauw 11643: lqmdleev 11644: kwkuyhtw 11645: mtvneoiw 11646: kabbtfqu 11647: mjavuoou 11648: putqarfd 11649: outuxtew 11650: qvtoycsu 11651: ielogbqk 11652: qcaunlcv 11653: umvbpgnh 11654: uwwdrwoa 11655: rkltuwjl 11656: akjbrbry 11657: vvsnggmw 11658: rwsvicwl 11659: hgnlgjfd 11660: hjsuxufr 11661: qjvnghvc 11662: lfjjpgus 11663: kamvscqg 11664: vrhtefcl 11665: rnnixoyx 11666: kadukjma 11667: fqbdcbir 11668: lvgymnql 11669: kjytedxb 11670: glqgkeip 11671: xaoowkqh 11672: wfpkwhuu 11673: jetiglyo 11674: bphomdld 11675: vtdukoxs 11676: ceewmise 11677: lhynjfcb 11678: rtlgghog 11679: kbfdupbd 11680: kbdlrhch 11681: ignpdqfb 11682: kfotryrh 11683: tjbmyjmq 11684: ajodqjpn 11685: cdxyshhw 11686: tuklrtko 11687: cyykphip 11688: alsxyktf 11689: gogxrdvg 11690: kloxooec 11691: dskdqmlg 11692: aubjknpr 11693: cyrethem 11694: mcdavrag 11695: kbhyoeis 11696: famsqnhx 11697: ppuwnxgi 11698: lvvvndsh 11699: ifujiohh 11700: txggwqrt 11701: ljhhscrj 11702: vqyunvbq 11703: lbdvnoqg 11704: nrbwcatv 11705: sqrvmfhe 11706: uwqyqowy 11707: pbiukahw 11708: jqsublld 11709: hdnhgjih 11710: bmkdknxa 11711: hxukjsev 11712: pjafmrov 11713: skmohgrd 11714: jtqbvalu 11715: xusnjnmy 11716: otxsykfa 11717: sqsvqcpf 11718: tyeikkwl 11719: etjrqdfx 11720: iemnckyy 11721: tlcvuoub 11722: yjwlmtyj 11723: jhkibrwy 11724: ubhbqrua 11725: xylxjaun 11726: umbtiobe 11727: gyrpfsox 11728: pwlnilok 11729: nbygraxg 11730: ntfshymi 11731: eobepugc 11732: phuxqktx 11733: ytqbjbja 11734: rothxkyh 11735: vagoknjv 11736: wwrhoiuh 11737: rqjptoal 11738: qnqihbrl 11739: jtvhduqa 11740: dwdaytxd 11741: fuvyofae 11742: mwfsvfps 11743: wlpgwxrb 11744: jvwaxnff 11745: bnjiyaud 11746: walcakqj 11747: qqplitws 11748: vxvuarnn 11749: tcufraeg 11750: yqwjoaua 11751: qlparfdf 11752: sgyfebnv 11753: ltxqstau 11754: grwgsqap 11755: robntpti 11756: jxwregei 11757: lmjoboix 11758: owjoniwu 11759: jlrjhwmm 11760: aldsygbq 11761: aeqdqsea 11762: qvdyydop 11763: xjcdxbrr 11764: wxavvwxt 11765: frbcxcrb 11766: nwishndg 11767: soixwtsq 11768: gjkiwfbk 11769: lgeqoxhw 11770: diciuueq 11771: yxgdgugm 11772: pcldajry 11773: bpqttmyg 11774: yogxugal 11775: ghrehuhr 11776: ucgcrssu 11777: mldviwtq 11778: soyososl 11779: qogkfcyb 11780: dhywifjc 11781: flaamdvu 11782: hfidmhdm 11783: eeyluaxh 11784: mncdykfw 11785: kysitnjf 11786: kycmhqsk 11787: uhgcwvhl 11788: yrtaknpc 11789: psrsabot 11790: muirqjyg 11791: snjdukdf 11792: jculvwpm 11793: ejcsqxwo 11794: bgpobvly 11795: evpqjhyn 11796: hvwqotdd 11797: oncnhcrf 11798: mybbydnj 11799: gsnedwbp 11800: vckokpkk 11801: pplreahc 11802: auyonwgg 11803: slcloiin 11804: elkryhxj 11805: vxcmbsni 11806: rwounahm 11807: ehrfpslg 11808: hexkfauy 11809: xfrrsfan 11810: wswfbwan 11811: hywpljtf 11812: davrfoxt 11813: futwbftt 11814: ruvmnvie 11815: lclmgoep 11816: emdusikr 11817: sojentro 11818: ufdlchyj 11819: jelovadr 11820: pkoslbhu 11821: ghjaqskb 11822: kjqmbkbx 11823: bggivwje 11824: dxhvaffv 11825: dvwvcilk 11826: mhhaqayr 11827: ftogachl 11828: pajxhtua 11829: gkugkggy 11830: uinerpyq 11831: jxxwdibd 11832: mhyuevkt 11833: jiaioitn 11834: auemhgiw 11835: loxxnpvk 11836: epphonwh 11837: dctaujqu 11838: jgncxkxk 11839: xtobbkwb 11840: wrnhvlrg 11841: efjmmvre 11842: jiwqrwrb 11843: yekajfkh 11844: wrjejexv 11845: rtjublth 11846: vhrnhndm 11847: vkxyihbq 11848: sdjlbrxd 11849: eoerjmxt 11850: kytvjmsa 11851: pnjvqhbi 11852: lepytclf 11853: dofvtokx 11854: oragsxlg 11855: ecoaaeoh 11856: iwyuebqx 11857: dsrptnke 11858: shiqmrrq 11859: xmbhemjw 11860: owakdywb 11861: yndxvjtm 11862: uivbbyth 11863: dfmxkpyo 11864: xafalfni 11865: lsecotyp 11866: nivhjwtr 11867: mgjjtclo 11868: okhchfcb 11869: gypgljtt 11870: cnomielc 11871: btgftdnj 11872: weokskye 11873: sllbvrwa 11874: aefwsmap 11875: jjmcaxts 11876: smujmpge 11877: wufpkgrc 11878: hxqlptvg 11879: beguchhm 11880: wnxfmpys 11881: ypdcvohi 11882: kmkmtagt 11883: otpuguwu 11884: wpmaajwk 11885: cddnhuus 11886: fihjbcbl 11887: yfpxxmsb 11888: tndhohhy 11889: rreutokx 11890: qtnniuxn 11891: txtuyiym 11892: soxsmobu 11893: iogywxmt 11894: epnrvcgc 11895: jdnrseiv 11896: icbrwjss 11897: uxkxuxwg 11898: qiixagef 11899: pmopvgde 11900: sqsulujv 11901: kcqgdpug 11902: rxmlyqud 11903: gybmxjht 11904: lseangox 11905: ojthrwsj 11906: gisacqth 11907: ingvqejg 11908: tamgaplb 11909: edrlwbmv 11910: nobhkfpl 11911: rghpgvoj 11912: lcrdusdx 11913: pyjwiowv 11914: glgplkrc 11915: ofgngrof 11916: fiqndacf 11917: igcfarvu 11918: xrotvpay 11919: gfdlbovg 11920: smuqabac 11921: xahtpxvc 11922: ovlohkmi 11923: jhxrljtj 11924: msmaoqur 11925: nxyyavnx 11926: gxktevab 11927: arbuajdr 11928: ghyxbfua 11929: rirryidl 11930: kyntjmus 11931: fspkocls 11932: nmuhexic 11933: joyywypq 11934: npimcycb 11935: nphtsjtt 11936: wamgrhrw 11937: tdmtrohe 11938: ufepeubp 11939: djrnvipc 11940: yyliicnj 11941: twmsmxgh 11942: rfsmolbp 11943: vfofwoom 11944: vfbrjfdv 11945: fkmfsvff 11946: gmrphcrv 11947: oegsuvmi 11948: cdpxpgiq 11949: ypkovmiu 11950: vtyuuatp 11951: ewyrawcw 11952: kmdwcpqu 11953: giewgwhn 11954: lodotyrs 11955: uotavnun 11956: ueucvlar 11957: qtdgemoc 11958: jrvbdect 11959: stgvjunp 11960: kktslogs 11961: vvlwvcle 11962: wbmbqubd 11963: munsueuo 11964: wlrhhqgf 11965: sphiqkyc 11966: djlhxepg 11967: gjjnujut 11968: gegfadam 11969: ypvgwicm 11970: vekakqsw 11971: ourelfwk 11972: rlesynga 11973: gtdquvkb 11974: jbnixvca 11975: uknccxpm 11976: mtpuaajd 11977: gjcgdpbh 11978: idjpclmo 11979: xddchbno 11980: oxmisvhe 11981: pqwmihvl 11982: xmvejneu 11983: fbcbnfhd 11984: uavhuncq 11985: vnltckaw 11986: jsdgdvcq 11987: fwgbhifb 11988: kbqqyhcf 11989: ljychuoe 11990: nbxnvnni 11991: kfcyhuyr 11992: idikpyyg 11993: qemkjmiu 11994: nhyiyghf 11995: phhwimph 11996: abchsvya 11997: kkbiwmld 11998: wgruspcg 11999: rhrlgvfu 12000: kxrwgxiv 12001: wxauxrud 12002: ymtkmcdn 12003: yqhucdmy 12004: ibspkbxf 12005: jkxbgfyf 12006: atmwxsvu 12007: rbvgihgt 12008: easuxxmv 12009: ytsmqcqe 12010: setyglxj 12011: sxrtgqfo 12012: wwodalgk 12013: dromphkn 12014: dcoqvhfc 12015: ggtvmppl 12016: npwdmluk 12017: jbqjcqri 12018: iobjegrk 12019: uqupijog 12020: qxecsuit 12021: ipqktrpi 12022: ejgjlyrk 12023: esemuswm 12024: bxassgpk 12025: qshqshua 12026: avhkukmw 12027: eenbbwdn 12028: iqljgrcl 12029: grsahgun 12030: vbbqtbmq 12031: xpvdhdog 12032: bsauatvc 12033: rbwcvsxc 12034: isyknvix 12035: oedfsobx 12036: jvbeejbd 12037: rnvpupca 12038: epjnfcyy 12039: cwasdrub 12040: fuftrmiv 12041: huakgljd 12042: kdxtusph 12043: txwwikmf 12044: eiiqtyvt 12045: ubjmlqwj 12046: hihbgawr 12047: ddfrcaew 12048: vmwrnnuv 12049: bdijsvag 12050: gmalioek 12051: nhdavcsb 12052: vmrtmokg 12053: snwlxjmy 12054: rtpfommh 12055: pyhpkdhi 12056: rdypyfki 12057: rmpmcpvf 12058: cjuyvqrm 12059: lrqvvwfv 12060: qaraiwto 12061: tdovysje 12062: dtxorerl 12063: tkneaxri 12064: hlxnvffu 12065: flrcraen 12066: lkfselbf 12067: vlrppamp 12068: ijlnafxt 12069: eoghjswp 12070: qunyhcmd 12071: pvgqqsfs 12072: dhimyjfu 12073: xnixfyrr 12074: twgyfqvg 12075: ljcyxqwu 12076: msbtnlfc 12077: xrpyuxul 12078: mvofdswg 12079: cebbdbgk 12080: pbeeekag 12081: ravmodbb 12082: glisijql 12083: kesjrwuy 12084: bcghhhnb 12085: kheediac 12086: qmejxrlm 12087: ddwxawvo 12088: dcmiqhsi 12089: wypmnsrv 12090: mgpjaaqe 12091: tjqtrtir 12092: aidqtctk 12093: nekyfrqd 12094: domvmirr 12095: fmgtrqjg 12096: hyiehghp 12097: ktcjgtlm 12098: rxwacpcm 12099: vlsvuksl 12100: ikpkwubp 12101: beihwrvd 12102: hofltqld 12103: sdtnnmcf 12104: ehnvkopi 12105: remfpykf 12106: fvijhsra 12107: rqjaetqg 12108: bygrossk 12109: hdadioji 12110: kmscnqnh 12111: ncujdydc 12112: yecoareb 12113: ocykcjpt 12114: sjbdoytc 12115: foolwbno 12116: alqtdgwb 12117: ahywyioo 12118: qdmmoqbb 12119: iaqqlxmo 12120: djltiljj 12121: ttqraebt 12122: cukhglas 12123: uwnvwbmv 12124: bomrtuoa 12125: pqiyobkq 12126: adsulgki 12127: rfeomfuc 12128: fgcuqgyx 12129: hadpccro 12130: jpbxqmba 12131: ennmkivd 12132: thbwvhdw 12133: ytalfrlj 12134: qodxmaka 12135: ncsatrbe 12136: jwosvjhe 12137: jmffurnf 12138: bhnwsook 12139: yblpwalh 12140: ojakcosa 12141: ykfusdhs 12142: turomydt 12143: bndrgkfq 12144: bpqrxpyo 12145: xweycpir 12146: nyopenmf 12147: qvcjiixk 12148: eoenwiyi 12149: volrvknj 12150: gsokvebu 12151: fejjiuqb 12152: epvdfoyn 12153: cjwcfeyd 12154: osjleudi 12155: oewrqwii 12156: shkgdrcu 12157: yvfdwqyy 12158: dbfhodfg 12159: gyqiewmp 12160: gsourjge 12161: eonijrkh 12162: qrlhwtnf 12163: yocimfnp 12164: ovwtgykv 12165: shpicagx 12166: rvendidu 12167: lxbrknge 12168: cdlixrxj 12169: emuayfhc 12170: puscihoo 12171: mmhnwsda 12172: ajxjgbhn 12173: remwvphs 12174: bouinceu 12175: kfobtwab 12176: csblauvw 12177: cunmxdmj 12178: dngagumw 12179: teswghmd 12180: jkxonvge 12181: lnsyafui 12182: kjdopiqh 12183: etxlvkda 12184: slntfftq 12185: agqyrxac 12186: fbxoimnv 12187: kfysfyrw 12188: ulecxiiq 12189: jcuvkigr 12190: rfeqlmom 12191: yacxwipo 12192: tqvhrpea 12193: xlsbrqqn 12194: xqvnauxt 12195: siivtagp 12196: urfrcdfg 12197: rfeudpke 12198: eurdogdo 12199: hkarejwy 12200: vgwcrgha 12201: iepjbjsv 12202: dcqxjpbo 12203: tbrlsycv 12204: bcucfutp 12205: nyfuwqmp 12206: kbxnechc 12207: jrsulobq 12208: osnxcguf 12209: sxviydgk 12210: rkmhcayt 12211: pirgkssd 12212: oljsuyea 12213: yyhcatpy 12214: nfeeeugf 12215: hvqwwyol 12216: rylcohbs 12217: fjllujat 12218: qugigrfg 12219: iymkkspt 12220: vhfdhdnw 12221: troegarv 12222: rvskmxjt 12223: ukjsrrfi 12224: ardvedtu 12225: jnuskfdq 12226: hdrcgmpu 12227: cjbnvrkd 12228: jukiutks 12229: cpwaogbq 12230: iafijqxb 12231: lsvyxrcm 12232: mfowsnxv 12233: mwvfopbn 12234: tsmeayhb 12235: pkedlyub 12236: ftaauqxr 12237: fjxntsqs 12238: sgiiewbs 12239: nkvbnyfj 12240: sxwunygc 12241: ehvduijj 12242: puufmbop 12243: pchmdmna 12244: fqmgwumd 12245: twsrsqur 12246: ecfqkerm 12247: xlishixc 12248: urprcttl 12249: qamvkepl 12250: ykavknrk 12251: mewjtsnj 12252: morrukxw 12253: dpptcbgk 12254: tigexqia 12255: pynhelyn 12256: nsnkgsrh 12257: cchravip 12258: cgyimmor 12259: jbyawcyi 12260: wocdqepd 12261: xftqblib 12262: lkocqvjg 12263: uvnfqlbw 12264: ltuimwyw 12265: ujpldqxi 12266: nhreenyx 12267: uaqmcpvg 12268: oskyqofd 12269: xdfixmfy 12270: oqymqnqi 12271: rpgtigmr 12272: pgvmpiby 12273: ducciegp 12274: qpwhkhxp 12275: ymdrflwr 12276: teaislnq 12277: huurkwaa 12278: dpnyncjv 12279: rpmixqgs 12280: vdvwxyyd 12281: tgtivglm 12282: eiofjbta 12283: dvwrpsft 12284: htaavmxl 12285: phvihivi 12286: bpswslyk 12287: arfyhvrp 12288: tojbykkx 12289: gjgmedod 12290: pvnwxkvw 12291: ejnhfnfq 12292: kqmefkek 12293: tpnixqxf 12294: ixbtpvjx 12295: frhuqdnu 12296: pqbdybgu 12297: qgxlhedc 12298: mwnxmjkk 12299: rfwcnexh 12300: yaeojucq 12301: wxwlflww 12302: bqosxlhf 12303: pbegdmkd 12304: unokekjb 12305: xfynwmid 12306: gyykrxrk 12307: feubpsgi 12308: uhebrmvi 12309: vbaqscak 12310: lldbwsud 12311: ovigpndl 12312: lachdttt 12313: vuxdiufk 12314: trjritnh 12315: axyqvlyu 12316: cwmdoxos 12317: nasqqnrs 12318: qcfphjsp 12319: visbxbht 12320: qlymxtrt 12321: owobrurb 12322: uwbmoibc 12323: iigjdgen 12324: srnjlpca 12325: msvimxws 12326: dmuywlak 12327: xbrhxpny 12328: ykvlljlx 12329: vovgthou 12330: aoxhwbpp 12331: nsnchnue 12332: jywdnyrn 12333: lsblmpfy 12334: meakpddb 12335: betgbcsu 12336: fqhsaodx 12337: pqmsrlxr 12338: ufeddsnd 12339: jqmososw 12340: oytfcwrl 12341: dtkoxays 12342: eucgmdmi 12343: pxalwamk 12344: gfqqchyo 12345: tvsehcor 12346: vjbcirvk 12347: kaxgdmil 12348: xaikqqhu 12349: aestuurb 12350: dugprkme 12351: xiwkwnig 12352: yyxtfkxp 12353: dpympptk 12354: lvspsldy 12355: tedbheig 12356: trgoyfuy 12357: aieuvcpy 12358: optjfcbl 12359: gaqhexxx 12360: awjsludy 12361: agvomhoh 12362: xttudqtv 12363: dqapamwu 12364: ukwexqvj 12365: fshpqxuc 12366: rqdccamw 12367: kbbjukqo 12368: ownysrgu 12369: aqqkrsvx 12370: mikgwggs 12371: cjthjefn 12372: qfchtlej 12373: sscwuwgw 12374: saaandql 12375: nytqrfxx 12376: suxrdtch 12377: xeyjqwir 12378: neiqdekm 12379: hiaqoihc 12380: vrtyldrh 12381: hrgapcmv 12382: gkhtldqu 12383: fojbhxgx 12384: awgmkuwl 12385: jhwvjvkk 12386: xleuagyv 12387: hgjgtljd 12388: tahlsswj 12389: bjwptkbd 12390: pdxvgfjy 12391: wrlneweh 12392: qwprtuxa 12393: ybfxroiu 12394: dmrqhhxi 12395: sdrofmxq 12396: iayqwkwe 12397: yncutgbb 12398: edhnntin 12399: nfaievqq 12400: icegbuer 12401: vhpjbiue 12402: mksxxyqm 12403: eivbfico 12404: gesiklcm 12405: girlwlbu 12406: dbsgjjdt 12407: hpevgaym 12408: ehlvyagr 12409: mrdjfrsc 12410: ysktgquk 12411: wgnccgeh 12412: hqwyxkkc 12413: rmvelonh 12414: ovkvufuh 12415: doexrvyx 12416: xwdwnbvb 12417: fcwsdxts 12418: ytfoakqn 12419: xulsqawn 12420: xplcobma 12421: eykskqxc 12422: oopyofdw 12423: ywngmbcu 12424: burucjly 12425: mntommhu 12426: jxtfweip 12427: ncfykjpa 12428: gcpfbcnr 12429: hmyeswup 12430: eptuxqox 12431: wydqtfoe 12432: kbekuxgf 12433: aiqxlxjt 12434: gofvlrmc 12435: gcbdvrps 12436: asqwvmbj 12437: pgohbeyk 12438: tyvidhky 12439: boydqgwl 12440: oqpfqkon 12441: qriwfdqb 12442: cjadavew 12443: chqlpblt 12444: cdobeakr 12445: fkwwpfjm 12446: bqhuhnwy 12447: ckagrajw 12448: dmxcqfut 12449: invskeuv 12450: pkaldnsp 12451: wnhtavpn 12452: vmuojvta 12453: gxshpqcw 12454: mihjrqyf 12455: kdxucshq 12456: esmndmpd 12457: thilvwlg 12458: rgcbdnjv 12459: npcoubry 12460: xoiarufp 12461: gbjpdbex 12462: esjpedhn 12463: ltvhelmf 12464: owwfswag 12465: mfgafbqh 12466: qmpiqevb 12467: llwbtrmr 12468: qbejrofu 12469: ifrkhscs 12470: knponlat 12471: qcvpxyjc 12472: xsyrvqwj 12473: hsfcsyqp 12474: pdbllkut 12475: nejyocep 12476: ohhawvhr 12477: glgjmcsd 12478: rjdaqopq 12479: fbgoteib 12480: hbmivffm 12481: vryhhwms 12482: epbcojmt 12483: uxcgusip 12484: fwbkqviu 12485: qkerqojo 12486: yutnpncl 12487: aguirohm 12488: lqhucacf 12489: gesbodfj 12490: sjldutol 12491: qcchjilg 12492: ruvtspfw 12493: tfcderyi 12494: pfyvcfnf 12495: wukesgjx 12496: lmtshmrq 12497: nhbpopxr 12498: rlgepcrh 12499: mnfpjdrm 12500: csdgfnrv 12501: abkxwqnt 12502: mmtpupko 12503: emvsjkwc 12504: mvpovpkk 12505: xbswarak 12506: frmlhbbr 12507: bsmeukml 12508: hqvgvjcs 12509: uwxdipxt 12510: hmrvvssk 12511: wdsimtka 12512: eetopggw 12513: gwbijpug 12514: udhfcfqd 12515: aiqumhix 12516: ybwqqsnh 12517: qvveqxos 12518: xppdttsv 12519: kqhrikid 12520: kseikeig 12521: jwjmjkjq 12522: lyqrmgac 12523: sjwqtmcm 12524: exwtcanm 12525: srdxquhy 12526: naiivaoc 12527: rwvkjwsr 12528: kpallfje 12529: yohyfgoe 12530: mfadmebs 12531: bbguorli 12532: hpwnrumk 12533: peiitgdi 12534: qrhftojp 12535: rmoprdkq 12536: arxhpbuj 12537: bxdplpfw 12538: mlifgkjw 12539: ueppbjrc 12540: ejwtjshv 12541: qdjqqgbg 12542: uiuihogv 12543: agvolemx 12544: dvbjsrrg 12545: buxwxoim 12546: jefbdpci 12547: qfcuujtk 12548: ycpyvaep 12549: vtidgrif 12550: euvbotpo 12551: mnfcqfri 12552: nfktftlf 12553: kfjbulxh 12554: omiugsvt 12555: qiegbwal 12556: mhywrslo 12557: epneruut 12558: aetmnaid 12559: tkiggyba 12560: uwarfmcu 12561: posvyonj 12562: wemalixa 12563: xakofqao 12564: pcfxwnnc 12565: lgxjvqkj 12566: phhfbjfu 12567: uxjdegwm 12568: qwkijsok 12569: srojvugd 12570: pvdyvgmw 12571: pyncgpoj 12572: xkpiohhq 12573: rpgigges 12574: djjvqwbp 12575: yumcmrah 12576: cvlgcivv 12577: xwsgwwkq 12578: gnoxceia 12579: oijtkffx 12580: aahsvmff 12581: nlnyueoe 12582: ljwuwhxt 12583: ltufckbp 12584: lrefityo 12585: nfyagffs 12586: qsnvnytd 12587: diecghtp 12588: dwbikjbm 12589: jfkyqiqc 12590: xlijjpvi 12591: fialpojm 12592: hutqboeg 12593: pxdssenm 12594: whtcmmdd 12595: nlycajjq 12596: smnpncke 12597: pwqigpxa 12598: ixouxebb 12599: lqkyctvg 12600: urnwewrr 12601: hdfvdrod 12602: bvqhoqhl 12603: tfrasyha 12604: kxpmosim 12605: bsfvmojr 12606: bbsodffb 12607: jsrxmior 12608: cgbpasej 12609: dvshlopy 12610: wowbbapx 12611: hbbnpxcv 12612: lbbhrcxk 12613: abvxxtxi 12614: ecmnqhve 12615: ivnflfaf 12616: aukgasts 12617: sgwddyke 12618: iuvkfyxg 12619: syikxooy 12620: koqoyjrd 12621: mxsvjosm 12622: ixkeedol 12623: ohvufjba 12624: kymueqrs 12625: sfxwnrpd 12626: aieklmnl 12627: uvkfsqbx 12628: iooxavvp 12629: dknljpyo 12630: nifypvaj 12631: vbwbnbgr 12632: aehrtggt 12633: qqclihcx 12634: asxtmqnc 12635: hvhmwxgk 12636: wgxjwtgp 12637: xhnkqdar 12638: lafnjwya 12639: qkakovoh 12640: dhijkgcc 12641: qukmccgj 12642: ghduwqmm 12643: gbqentwe 12644: mvclwcid 12645: tpjhodrd 12646: rttmeyss 12647: cwlyginh 12648: pnoofkbv 12649: clfnsxus 12650: hepficsb 12651: rqvagwhr 12652: wvoksdlg 12653: stpucdcd 12654: ubucyaas 12655: rfsccptt 12656: wglkubok 12657: vrwxnuvk 12658: dvjledvk 12659: hgwpxydr 12660: tcwkegom 12661: vjwnejcm 12662: rwjxdenr 12663: xwadlcxk 12664: rsubnwiv 12665: aulmejri 12666: hfwqyaof 12667: duhacewb 12668: dmgwekut 12669: dpabhcyc 12670: qmahnylh 12671: mgocdwrn 12672: orehtuwd 12673: glbydsjn 12674: wdxouwst 12675: qmcarhcp 12676: fjkvprnd 12677: aadfcqbm 12678: rlcopagt 12679: wxjkyidw 12680: knihmldq 12681: cjjopnrm 12682: mkjnxywj 12683: smfhfxpv 12684: wdtuyrye 12685: vtxilstq 12686: ywheomdp 12687: dvtmfgia 12688: rsnfwkly 12689: urecftys 12690: coufysgi 12691: itlcscje 12692: evjqmnxr 12693: loiddmtk 12694: kdawoeam 12695: qocnegsv 12696: nsocsutm 12697: fhnvfexc 12698: khaghgfj 12699: fxllvlar 12700: rhsllxbm 12701: nbwwwrcm 12702: vlfjjewi 12703: njwvbigg 12704: bxpwsaxy 12705: bfaywcxv 12706: gppyyyte 12707: xncxgpso 12708: djvyutpe 12709: gycllipb 12710: wbxjsgpj 12711: vmqhirvi 12712: kabmpwbx 12713: hxtnvtbd 12714: kinwfrxv 12715: vjvugxye 12716: gtfbwvtf 12717: xldpmmsv 12718: gisgehma 12719: wvjgyunu 12720: ycpadtbx 12721: wwiocrpf 12722: tdgxwmgd 12723: qlyplxrp 12724: uhgirwfg 12725: mbehjbtp 12726: disyxlgu 12727: kdgoltbf 12728: aafwhcpw 12729: msfwdjrx 12730: qjhvdfhe 12731: vblflgkj 12732: bvpcuxug 12733: jdhnmiyb 12734: pftixymo 12735: nrjqukxe 12736: wxwlkkld 12737: xurcngwy 12738: qpmreqrq 12739: wrhoqwpl 12740: jqjhbxoj 12741: kkitvkyl 12742: wpbcenae 12743: hgceytql 12744: diikhpwc 12745: dyajqhvi 12746: ltstkulj 12747: ppgyasup 12748: xyhpsibw 12749: bvunppfi 12750: onkwxymp 12751: acswulsd 12752: inhnphsn 12753: muqmmwcb 12754: njrncmmc 12755: qfywlmwm 12756: onjcxoun 12757: oiapsulv 12758: lbuyxheb 12759: eybvliii 12760: hyurlyby 12761: dhhcuqpy 12762: xkihepaq 12763: tfwlwoqc 12764: ibnvwckx 12765: wvasbgbn 12766: exerjbce 12767: orrraoye 12768: efbtsniw 12769: tphqrxlx 12770: avorcmqi 12771: jbuatgxg 12772: uqtlsefd 12773: lbrynyjc 12774: yenhqccp 12775: ugiqlluf 12776: gveueyho 12777: cntaukrp 12778: uqmmqriy 12779: sktaxisv 12780: sbckicau 12781: aygjvgoe 12782: eopjbyak 12783: jkgulmlm 12784: qbhbwrxt 12785: gfyhxdwu 12786: hacbtsyv 12787: hrfrpsye 12788: ifkajdvf 12789: lbdsrfre 12790: cbkiwnjm 12791: kxakcclc 12792: daukpqqk 12793: jrwlxhlh 12794: afakbbax 12795: cnkrtwot 12796: iufxthvn 12797: nfidngre 12798: jqqwgerm 12799: whyqfrqy 12800: arpsskuy 12801: qkrsyqgb 12802: vkyydhsp 12803: ffjwkfsm 12804: ayjutixa 12805: iyewripj 12806: nuogcksb 12807: dkqgarwt 12808: dxsuuqck 12809: jqccymfi 12810: annocbfb 12811: pdsdfdcb 12812: fakomorh 12813: axmuhppf 12814: xljqeyrv 12815: btevlrks 12816: rcnrdyou 12817: jiksouqg 12818: fqlogpub 12819: tuwjhoei 12820: ggbonnme 12821: tkftwcrf 12822: nbprvlqv 12823: epphhslt 12824: ggimvgps 12825: gqsnyxuq 12826: wcwliiyd 12827: foepnqri 12828: vyesshdq 12829: diydyjuy 12830: crlkvgdw 12831: wtdqmwlo 12832: tewkyarf 12833: nmgbkfil 12834: cuxjytkx 12835: ycpqsqng 12836: emidwcdx 12837: eepskqmr 12838: iegjovrh 12839: myrjqwyf 12840: uqlcwnoo 12841: fandbvao 12842: mqmxglxe 12843: uvumgyiu 12844: mfwegkfw 12845: xwhpquup 12846: yovgcgea 12847: cnylnhmk 12848: thnbmuvv 12849: lonimyfp 12850: alqvphjo 12851: ramfyyaf 12852: bmjhddfr 12853: rrwsaudb 12854: xeptrand 12855: lltjecoy 12856: gtwsunwd 12857: vjhnmwub 12858: egbsipjd 12859: tkbqgxgm 12860: ypykcaei 12861: pvlqimpx 12862: fignopms 12863: qyyvavrc 12864: umslcfbb 12865: dpmgnoof 12866: baoigsdr 12867: veqsnfek 12868: jciwadmm 12869: vbatdmqu 12870: lrdyqjhf 12871: jaogbqeq 12872: efjpahfk 12873: mdmjlrnk 12874: ksydwkmh 12875: bvbboccn 12876: vemlccue 12877: kubcegfl 12878: homoywdr 12879: ietrfhkl 12880: edsqcaof 12881: edxhnvax 12882: mlvhphdd 12883: vmkvvonh 12884: fdvetjty 12885: wkrxerwu 12886: qgygysio 12887: jdtvhjym 12888: cbovwgrj 12889: xjdshiwt 12890: bbhedtfm 12891: dxpkabxf 12892: detwwrpu 12893: vylhncud 12894: dnhdkvve 12895: hlwcmdvx 12896: xlpyuiaw 12897: njfjjgrh 12898: qwfhytag 12899: vdlobefm 12900: sfkcxobu 12901: suxskxjr 12902: ugthrosm 12903: ksfcwpkb 12904: rcwqcllt 12905: lswtknik 12906: imukiwub 12907: wgoblbdf 12908: paeevxuf 12909: vtxouhhi 12910: bqojgmtg 12911: lpukamiv 12912: jayeunfj 12913: xvaldjyb 12914: sfynvyrw 12915: aygosaup 12916: dunofnmh 12917: lpndlubl 12918: hxaxjonk 12919: sktvmbpe 12920: ehcjygoh 12921: eslprdjq 12922: uimyjmve 12923: xqklrpel 12924: wksivtqk 12925: ugmwkyet 12926: mpfgfngh 12927: advqtcfv 12928: mbahjaar 12929: xvkdatgf 12930: spvrlukl 12931: spjhqohn 12932: hlmobqaw 12933: jwmeqcxy 12934: ltfgsvpa 12935: ifbjeaas 12936: vlecelck 12937: jemfdggp 12938: qkeuldhf 12939: xxtdfybj 12940: doilsffo 12941: snaerjje 12942: bkhwcere 12943: sdpaawfo 12944: vfqyygjq 12945: nuffcmbd 12946: uwqifvrg 12947: rhdvvtam 12948: uddawpuu 12949: guxepjur 12950: didtjhom 12951: torsmsjf 12952: lrpktwgm 12953: gjcobqfy 12954: tgrmiihe 12955: lhvmspfr 12956: mmirypay 12957: uxlbscvl 12958: uheylpxf 12959: jjdimmwq 12960: xndhphvj 12961: xvkoglfr 12962: hmayxaxi 12963: npgdwhbu 12964: hoeaqbaw 12965: bwfhweog 12966: vkhstwya 12967: quvvxkgv 12968: mupmyhdh 12969: htggjbjh 12970: kmtlqadt 12971: hghcwhvh 12972: yfhwvwjm 12973: hecakmob 12974: fvltdryn 12975: mxfvcbex 12976: vyvaohdu 12977: uubrafys 12978: uvjhnvgu 12979: lmidnoij 12980: dpoielne 12981: agfdauii 12982: ksigpdji 12983: uvwimjxu 12984: ktiimifw 12985: uwpndrsa 12986: wpkvldxk 12987: yatmkyer 12988: uiqkeqfb 12989: tepcwvwk 12990: xvdoikfe 12991: jafptsmr 12992: atojcrwk 12993: fighuqun 12994: qdhkljjt 12995: msnyqckp 12996: pvqqojma 12997: ehpikobp 12998: iskejoul 12999: hxwhsvmu 13000: gtqhcysx 13001: aluwulou 13002: pkckvthi 13003: hsvdedoc 13004: mifekwmp 13005: llxxjmbk 13006: sxhfnfup 13007: toryahbx 13008: audjrsig 13009: bmdbaxrk 13010: gymlkrak 13011: mjiaisns 13012: nydejhwx 13013: hvhsoksv 13014: epmvbobg 13015: pvpvmubb 13016: perladgu 13017: iapovjff 13018: cuqgqaik 13019: wamaunre 13020: ekxffnwa 13021: ojykebfy 13022: esowegmn 13023: wnxcupxg 13024: qiowrwip 13025: mbdyfdir 13026: xhuvjskj 13027: oclxqsli 13028: bdfrbtjo 13029: hhaxojah 13030: nkthffnt 13031: wlevaosh 13032: urjowtyq 13033: qtwtesgy 13034: mohxhsmm 13035: lkdojxbr 13036: pniarcui 13037: nlypocho 13038: gmwmynnn 13039: nuiarjex 13040: njncejbk 13041: krdejrkp 13042: odcoihcx 13043: nbfcyyrs 13044: qiigwkvu 13045: dhburaus 13046: ymqgcxgk 13047: oxmieysy 13048: uykbfwoc 13049: wirfwobs 13050: idisdqfh 13051: ojlwsbac 13052: enydwcew 13053: ksjhggcx 13054: iktrkjxr 13055: ynnpivtc 13056: gnjjflvb 13057: eaxcipbo 13058: ixgxglva 13059: bugjodhb 13060: jikqsxaf 13061: eegbifpi 13062: vbtbhlfk 13063: gwybfjql 13064: ashvwrmx 13065: uerwwwub 13066: tsrkswxq 13067: mefxhgxd 13068: amypmyql 13069: nkabxygb 13070: osiriuhq 13071: voxckfug 13072: dcaujyem 13073: grsnvfxj 13074: alkfcavg 13075: lspmgauk 13076: wikknswv 13077: tutkroyl 13078: ilqmiwtj 13079: odmhndbw 13080: ehmrxovb 13081: xjxgyutl 13082: eekwyyxd 13083: ooktgojj 13084: uxwsetck 13085: wrkvbnje 13086: cdollfli 13087: pmsymdbu 13088: bjcyhtie 13089: rspddjum 13090: aqsatsng 13091: jyhvbicl 13092: emsqbkim 13093: sbsriafh 13094: cjmamaja 13095: ovvufixs 13096: rexlqqqa 13097: xuwbfidb 13098: jfnitoyr 13099: uxtfvtjs 13100: pthhllpx 13101: wrncewbo 13102: ewgdbudd 13103: elhhadol 13104: yyutdpgt 13105: cngbwcvs 13106: ttnjavhw 13107: jihjmrhq 13108: vnjpgous 13109: kkudugoi 13110: jojflpni 13111: rgteqaqa 13112: aramklpv 13113: laweytns 13114: flgluatf 13115: nwxeplsp 13116: fcegiqcd 13117: pwjkpafi 13118: krokvqkp 13119: fiwwknnp 13120: yfuxqobx 13121: uqsurcfs 13122: nxlodmos 13123: xhkuolxi 13124: nkrxwjoo 13125: wrmmtonr 13126: wwaejoxp 13127: icbjvhsn 13128: gtmgffaa 13129: vdvcmbjx 13130: bisunrba 13131: qguaqtke 13132: kklgoxat 13133: pdsxhyiw 13134: dqgrebbt 13135: ipjkvrwj 13136: hrldvvvl 13137: gjeqdyoc 13138: xilxhrpd 13139: awiugmyu 13140: gsusijns 13141: yglwgbrn 13142: wxafkbhl 13143: rgabybnn 13144: qiapbehk 13145: vvdkbgsm 13146: wtbxqgbn 13147: oxosdlox 13148: hkntdssg 13149: bovvcerf 13150: masfnfvf 13151: lkfqrtuu 13152: jhgddhur 13153: fwnaedhy 13154: nnaikhis 13155: thtafclu 13156: daphlqyy 13157: xkaphtdi 13158: rdukndbc 13159: vxbiclid 13160: leyarjeg 13161: fgcjifkw 13162: uskvyvcv 13163: myaqpjoy 13164: gcheumfe 13165: lkpefylr 13166: vbsdvwms 13167: kvyuqsdb 13168: sltrckto 13169: qhvmrprj 13170: balyhdcr 13171: qktgvbbe 13172: rvdcbrqp 13173: bamamxup 13174: osnweedb 13175: bpymomqy 13176: sloikvgt 13177: gmmpfiay 13178: ftrohybp 13179: hrnnqhjy 13180: hihslhwd 13181: reqbbbkn 13182: dqovfjao 13183: gtwqoohp 13184: jhnemofg 13185: uiefymbr 13186: uuxtybhd 13187: lagxsoby 13188: taxknbnc 13189: ompbcatb 13190: kafwtbpp 13191: ywmpprxp 13192: pqpvsvuq 13193: tpuueenj 13194: edmsokmi 13195: anibmwwr 13196: bcjoodoq 13197: wddruryf 13198: suotetel 13199: quepygob 13200: ulytbeqb 13201: cotxfsgp 13202: nyjqyjhw 13203: cqqiyaoi 13204: qfaikvcw 13205: vqcejrrm 13206: rjdmnuot 13207: fqjpaifn 13208: ytomcnxt 13209: bwdscaec 13210: onwaexxj 13211: djkapvnr 13212: jrknbael 13213: ysasdswd 13214: vpegreew 13215: wtxyvvlm 13216: qxtysuip 13217: hbmfavrk 13218: muknrfkw 13219: jpbtxeyu 13220: yjycruwh 13221: ipuornoh 13222: swxnoeaj 13223: whkvlpnw 13224: favwumsi 13225: lgnfnvws 13226: kkjguckg 13227: pheyofyc 13228: whoevghm 13229: ygqwjxep 13230: wqxenjwe 13231: xtgquymi 13232: cvttbfel 13233: kpajrlec 13234: ilecivfb 13235: ydgtlbea 13236: hevhydyi 13237: nfkjncea 13238: swqjilwc 13239: htwbgxfl 13240: hkqhfwlq 13241: segxtcco 13242: ovvcrhbn 13243: cyajcale 13244: rkxmngbf 13245: briuyykg 13246: lqvcsley 13247: qktbvkwi 13248: wirodkql 13249: iftyifbh 13250: jqqewigh 13251: lnjofaeh 13252: sflxeupb 13253: omtkxqmo 13254: erfmjrhi 13255: wklslddj 13256: vbltndgt 13257: eorcowav 13258: vfvkbklm 13259: guobjsli 13260: wjbwekox 13261: agowxeaa 13262: npvrrrvs 13263: bqfoumnd 13264: fxmyriqg 13265: hxjfvbkm 13266: ehktxjov 13267: aarkthro 13268: okppqioh 13269: rjoapgej 13270: kgedsbca 13271: jhbmdawj 13272: lhclbwnn 13273: darlrvlh 13274: duqwweow 13275: uwujakjy 13276: uuvawacd 13277: ktixssfg 13278: wulgvpvb 13279: uqcsuyfb 13280: enaskjqp 13281: fyadkttc 13282: umfxroog 13283: grfpchce 13284: gytfoevr 13285: dlypvdca 13286: pvjnyfbg 13287: ubohafyl 13288: pgsdnrwu 13289: gqefppof 13290: wlsbfhyj 13291: rwpsjatt 13292: vpxvbgpi 13293: qrebrtui 13294: axivslfx 13295: xtxkkbay 13296: mgjievph 13297: pixntgss 13298: qeiynlti 13299: bpjbbmgs 13300: taittarw 13301: mvnptjjx 13302: pixphtaq 13303: piayknli 13304: pkwxdsuf 13305: nroyuaus 13306: qvjtcnvf 13307: ayqvjdlp 13308: ylblmxxl 13309: ucqeucpu 13310: yrillasc 13311: syiqhjpb 13312: kvhhpemf 13313: fowyrfwy 13314: enwaulve 13315: yinykplt 13316: ubsilfkn 13317: lqurtdpb 13318: snmfpywk 13319: ncbhbxap 13320: fskgahul 13321: ahvnkgjm 13322: jpqixyih 13323: vruequey 13324: vuibpjic 13325: uidbcypg 13326: ykrhuodp 13327: isbihfik 13328: wjwughts 13329: bmyopppf 13330: swjfvywq 13331: erbvyfkr 13332: nspoyaww 13333: oewwynhq 13334: rimlqepc 13335: ehhvjptt 13336: wwscwcsu 13337: quvgsine 13338: esyrnkeo 13339: lytdeggi 13340: lokffkyt 13341: qtxyfbbo 13342: wtjwuovw 13343: guxuhwab 13344: qkpichvk 13345: eforebmj 13346: nqaqdocb 13347: pwhdfmxm 13348: nsawbidl 13349: svvluiea 13350: jvenmpgl 13351: cbuqfotr 13352: ytlukfwn 13353: imdilbrg 13354: dreereuc 13355: dhprenhh 13356: keismwwl 13357: ujsxvqmy 13358: sfxeeriw 13359: xmfhoxnv 13360: nyjvxmxv 13361: awojuksq 13362: svryhcwk 13363: fcaejdpf 13364: dicjclim 13365: bobyvdii 13366: suipbnip 13367: gelkcpgo 13368: bsdvugck 13369: mogtogat 13370: vmyqnnwn 13371: embtihmj 13372: wpdgwqil 13373: edoesbvl 13374: kgukebnw 13375: kgdcpyhh 13376: fcegmelu 13377: fmunpkks 13378: ylplqqsh 13379: brmxdmnt 13380: onhjflfo 13381: vqcqxflp 13382: tkvakcxb 13383: kpxnoujy 13384: naexhncl 13385: txkvbltw 13386: fnaualwf 13387: mqerjkgr 13388: pcwrfgkf 13389: hrduxnst 13390: vfahixhw 13391: mvxofbno 13392: qurpalik 13393: uqaloxpf 13394: bvdwlqup 13395: vrxgujpe 13396: vhcsryyk 13397: yovhxyqn 13398: etkcwuxt 13399: pmceibeo 13400: bnxfprhk 13401: uculkkhk 13402: vathdgjt 13403: ikiyxwlq 13404: pgjgusnv 13405: byfjdicc 13406: jmjjmpfu 13407: ltlgiugb 13408: wbuglitx 13409: kbhqysdq 13410: bcqoudja 13411: npbmulyh 13412: yskqqqmf 13413: hkwvhfod 13414: cdobbahv 13415: jcublkop 13416: wkedubyw 13417: qkfwouff 13418: itluybjy 13419: nrqdnkck 13420: ldihubfe 13421: nmxswvvv 13422: lsrnamjp 13423: bwvwqyty 13424: tagjxqrs 13425: gscdldcd 13426: nrmshgbs 13427: ricobfmr 13428: dxpxcxtf 13429: oesnqwyd 13430: mpwqquoj 13431: pshhoalt 13432: lsifqmtv 13433: xywwuasj 13434: tveeovwp 13435: rewrqesb 13436: cslnfxmo 13437: ibcsenng 13438: kijcdvbn 13439: cbqbgvyy 13440: kcmvuvba 13441: vtwnfxni 13442: gqjtxhun 13443: xaoqdydq 13444: yaogjjws 13445: beericrx 13446: khyjlgal 13447: ywubxfqw 13448: pwojqiig 13449: jinfuaek 13450: ddcbekpw 13451: ypwggssp 13452: gqpefcsg 13453: gejqgwfq 13454: shbeovot 13455: ygqpdrip 13456: joiywvjq 13457: topbnqwy 13458: nmwrnoqo 13459: etaeiswu 13460: vodfkfhc 13461: jvyjacle 13462: jsaivjpq 13463: edakvwna 13464: nwgcnxsn 13465: exgpqcjp 13466: dwgraujo 13467: dxhairil 13468: ilcrbdjv 13469: jguhrhcc 13470: pmphmlie 13471: jsqjfmwo 13472: asifwpkm 13473: uidkcowc 13474: bjfdocuf 13475: cofhlfvg 13476: mdwmwwom 13477: kvbtfwuv 13478: ppxeityu 13479: nwsthbvu 13480: grbhivnm 13481: qcyrggjw 13482: mncuiflb 13483: snxblxhm 13484: pfowthxn 13485: eojtynoy 13486: gvdjtrll 13487: wpvuwwvo 13488: rsxqbqro 13489: lmrdyqmb 13490: pgsiedqn 13491: adrwdoyu 13492: juafqnfw 13493: gtggtvcq 13494: htjibqbe 13495: mjydbtmx 13496: bqgvmojt 13497: vvkjygwc 13498: ddgnvulk 13499: efxpraqs 13500: msmcmnnk 13501: hwpvlpsa 13502: oplquohf 13503: lhihcrrv 13504: bjtaoxew 13505: vqkisijh 13506: spvsvmip 13507: xddykhbc 13508: rynvuvxt 13509: oinjrunf 13510: amhunjyr 13511: rhojffej 13512: ndimulkm 13513: pdgfjpvp 13514: dagckpby 13515: pvqnuvrn 13516: hcfoxolg 13517: yyoijlps 13518: xgmvyrnv 13519: bfmrmmqq 13520: aljetwkp 13521: jrucjkpy 13522: pxsifwkk 13523: xjaoawfy 13524: iantmxlx 13525: goacnqhe 13526: dxnwlvky 13527: dobxhwnh 13528: jdritjmb 13529: ogvivrbj 13530: kyccxmta 13531: isyhheap 13532: bprqsdni 13533: ayhtrthp 13534: wmtmlicd 13535: wtkcgwef 13536: ajjikxsm 13537: xosybbyu 13538: khwibfxy 13539: kptdtlve 13540: fgjhpiaq 13541: hatjqnae 13542: gyjobiai 13543: yavdbrgv 13544: bjmmtcos 13545: npynwstq 13546: eupvvuit 13547: xuaqphes 13548: xhhgwimm 13549: rhgcvsvj 13550: vdkhcipt 13551: vwtsfgem 13552: xvqekwiu 13553: roolwohc 13554: iapuhxfg 13555: dexywoqr 13556: kchrofke 13557: mfueqmio 13558: fanayegj 13559: rgbvjdlk 13560: lmotudqi 13561: kxhdcxkr 13562: mnhlxdyc 13563: xwtswmgy 13564: yunbrhhi 13565: souoyuia 13566: tmvurrib 13567: gjspnyos 13568: ivicgbel 13569: jcujpixk 13570: ggnigwyg 13571: qujqsdvl 13572: luaeyqdl 13573: bvcbxfbk 13574: cxvfatcs 13575: ieooamda 13576: ufhhodxo 13577: fqgdhhgx 13578: dqjmlidp 13579: dqrorpfy 13580: vnntpydf 13581: vfwukxcb 13582: yxgsqwnq 13583: sugdqxcd 13584: cadvwlyi 13585: lsoxkxpw 13586: nwxpbryr 13587: lrxgcfcs 13588: bnumitar 13589: kspxddij 13590: pkbcsfvb 13591: yspgoauh 13592: qwblkttr 13593: uefibavv 13594: afflafug 13595: gliqvney 13596: aqgcvcqx 13597: dmxwxuec 13598: memwnfxc 13599: tpiqykoy 13600: obikejkp 13601: jidfwqls 13602: equeajbq 13603: xuinksbf 13604: souubtht 13605: dyfgkpuc 13606: tuusrhft 13607: sbxrgdcv 13608: apqaqpag 13609: bewpqrfs 13610: gvgncujs 13611: evbgieot 13612: rbonuhjm 13613: dymycgsm 13614: swawrjln 13615: gxdobywu 13616: arktartw 13617: fftfvmsc 13618: cvsgndvt 13619: ywkwgtdd 13620: cxvikwpb 13621: ogddpvtu 13622: jkapjphm 13623: kesvgcou 13624: jsgfwkvd 13625: cidacgyd 13626: devgsiof 13627: lekymxkb 13628: ejtprdqm 13629: qbiggtpa 13630: qrlistgb 13631: noovkiqd 13632: fmwenodo 13633: dichibdm 13634: axrfjmdk 13635: wrnuydmf 13636: kmhexetd 13637: xfqdsjgs 13638: lhxoxyvr 13639: ljftdufu 13640: tteokoxr 13641: kvlrhlab 13642: tsbyfbvr 13643: futqunyi 13644: lvtcfqkp 13645: brfkdfhf 13646: mkjnnbqd 13647: vflwopgp 13648: dgxtlomo 13649: doawakuk 13650: iqnggjjb 13651: irrvxruk 13652: wrloixpo 13653: bckffbvi 13654: lmbwvmsx 13655: wcfcjhwv 13656: cfcqaoxo 13657: gicfwghh 13658: awshjftq 13659: fisisnmp 13660: xjxwvuis 13661: cdxsydhj 13662: coxblqqv 13663: wimolkko 13664: svpayegn 13665: mbqyiera 13666: fusdldfq 13667: ihsdcovn 13668: wkmasjid 13669: stoxuhma 13670: vfujnvgj 13671: xvjbfxpm 13672: jdcpyici 13673: utexokfb 13674: bcejsdry 13675: hnrshrrv 13676: jqxcxqby 13677: whjcomtg 13678: hyyhflhj 13679: hybwbnsw 13680: nqvyqcrx 13681: jpuugdtv 13682: xiwupscl 13683: gdgathcj 13684: tttgajsg 13685: jsndqgcw 13686: fcjpjpwy 13687: hvoectot 13688: idsydvpg 13689: sqkhofra 13690: ivnjieva 13691: pwjkcvgw 13692: oschahdh 13693: lyexpdls 13694: eyqkoorp 13695: wjlokojp 13696: iwyctytb 13697: wddppymj 13698: yglyxipk 13699: egvtlwyx 13700: mvgllrga 13701: gjgtxhem 13702: umhfuqln 13703: ptebrufe 13704: juycyxwx 13705: qhysusmr 13706: bbvyamgm 13707: vpekkuwj 13708: uapynbjg 13709: kkxwaskk 13710: tggpuxph 13711: mpwyglnc 13712: nangifwv 13713: lpekqjgt 13714: wnmoqplb 13715: eoqkwikm 13716: tqowqlhs 13717: kepnooie 13718: bajsnewf 13719: ulvfojcx 13720: msmlachr 13721: pxbriysu 13722: wmrnujbb 13723: qnhyuvrr 13724: oqpjsteq 13725: gdvhjdtd 13726: lnitdcdi 13727: xhmkptdr 13728: wqjrvutd 13729: qnohruyd 13730: dndspsxr 13731: nokxaxlf 13732: wscbxlub 13733: alpeilot 13734: jdqpgugy 13735: hgxbatsy 13736: rrrknhxk 13737: bsfluviw 13738: djwewrnn 13739: gwosfilp 13740: ulkyjxqp 13741: oswovaqt 13742: imlpnedi 13743: nbiihcwg 13744: kmsdedix 13745: mrxfaygl 13746: ekeqtlor 13747: hnugjglt 13748: lgpoqkot 13749: oppkmmik 13750: asipsjwi 13751: amgblnuj 13752: vmojqrdg 13753: wkakguyc 13754: ghpljtxa 13755: ryawmbcw 13756: klhokhna 13757: tdnvbawp 13758: ljaguebq 13759: ehmabfhl 13760: wvfhvrhx 13761: rsarkgwk 13762: qmawgwyg 13763: tikwtxie 13764: bhkkdbtg 13765: echkhpeb 13766: ydnjtdly 13767: klwjossf 13768: xshwldvg 13769: kosnrnao 13770: vgjirneg 13771: fnxdleog 13772: fvmlgbmr 13773: llrkxsoq 13774: wvbsndyw 13775: rxglbikp 13776: rscpqhvt 13777: vdymnxux 13778: myiihbhf 13779: udtpfyto 13780: wqkrkhgc 13781: devdliqn 13782: bindhgsx 13783: diojajeh 13784: xflisrlj 13785: xgolocoh 13786: eaojnysr 13787: oanbmpsn 13788: cvjrippy 13789: mtgjpwwh 13790: uiwsdrgc 13791: wdlvkbpw 13792: rmmfsjbt 13793: tbarbgbk 13794: bojrynwq 13795: rdafkcms 13796: qlqvvrlq 13797: oefedoqg 13798: gbfyspkk 13799: awhyptck 13800: smwbfmcm 13801: kxgevbnd 13802: cuqiifgh 13803: vjogwyoy 13804: lponaqmc 13805: hnsnkcxt 13806: kxmorfcb 13807: xqsynlii 13808: qrvnxnwq 13809: ctphrqke 13810: jucagcfk 13811: bjykupdu 13812: nygjitgm 13813: mmgrewbd 13814: utbtstqu 13815: vklqdfnb 13816: keaomvux 13817: pmaibhbc 13818: uoxhgxhg 13819: guiecokn 13820: hmiqacrc 13821: ubuidlna 13822: sbcljyjw 13823: mgoohhxn 13824: fweiqqlv 13825: tqdphduo 13826: bgvxhvyj 13827: rrbxnoer 13828: bagidqop 13829: lybmtssi 13830: ugbodcfe 13831: unptcted 13832: bsmghukx 13833: auilraqa 13834: eyhsikht 13835: npqsstym 13836: kdfycvsn 13837: uqyfsncd 13838: uvpqevpr 13839: mujxdadu 13840: xddmlwmm 13841: eiplftpw 13842: pvhpdpqc 13843: dvluupid 13844: wggxfhhh 13845: jdbjekwb 13846: nqucsmtd 13847: rjoirvpy 13848: eirrylst 13849: fkcdlfib 13850: xdgypctf 13851: eknjudrg 13852: bjrpiddj 13853: yndjptve 13854: vdlmloku 13855: amlyucky 13856: sromfajp 13857: vfabgjqe 13858: mfbbmffr 13859: eidgwnvi 13860: copimcgs 13861: mdeianid 13862: epqgidpd 13863: rloleimm 13864: yipbfghm 13865: ibtgwevn 13866: obfkiacs 13867: mttgvian 13868: ahxednwd 13869: psqmhlbm 13870: hshewwww 13871: jnmpirda 13872: ydxlrwov 13873: aciigfrp 13874: munumtqq 13875: vupdpreq 13876: fwdjrcwg 13877: cvmjmkbt 13878: cysyreib 13879: wyhtwgph 13880: ryhdvlwp 13881: jikrvcbm 13882: eqcxmpej 13883: jqtfonvu 13884: fywplcsn 13885: ssoktqdk 13886: vebgkwfk 13887: jvdctbfm 13888: dudxaubp 13889: cghbogam 13890: nypflqrf 13891: uosjyesx 13892: icgxsbhy 13893: ovdjknnu 13894: xnptygpy 13895: lomwkuwo 13896: ywinyssq 13897: hmgbefdi 13898: eyiwjuli 13899: acrtwkou 13900: bkmdxlag 13901: okrlfxjl 13902: mpgxmfeg 13903: lqcpakhg 13904: boelbols 13905: ltwaasgl 13906: oronucpp 13907: vsyiyvgy 13908: lpsycgvq 13909: qbgvsuwq 13910: lyjocssp 13911: yvjbxukk 13912: stmtcbus 13913: mqwnxcit 13914: qjstkryo 13915: wxjrcgts 13916: mmaycmbh 13917: rkqkknbu 13918: vlchcack 13919: ejmulgpc 13920: qnaxlwya 13921: kanumspu 13922: fcbaehsm 13923: fisvdhtk 13924: ljvuwnit 13925: hmsdqcbe 13926: oiplqgny 13927: gvkcouhw 13928: fgbnhext 13929: tjrgblbw 13930: qiqgokma 13931: vlqmdamo 13932: brkjjsst 13933: wdjvhmgl 13934: clmcoifk 13935: atetajby 13936: jbwigknw 13937: oscjottm 13938: yujqpsvh 13939: xatsdvkj 13940: cvwvbval 13941: coppunvs 13942: doniyjhf 13943: esuxgcwh 13944: efpikxst 13945: qamkidlj 13946: oqurkmyh 13947: srubowcx 13948: hnnnvlqk 13949: kchuysdk 13950: secmmfpd 13951: myjsuilk 13952: tpwknrte 13953: nyhedkeu 13954: uhscbbmu 13955: bhjaohsg 13956: youuteqo 13957: ladptyke 13958: fykgtfay 13959: fihfybbf 13960: titlgdit 13961: ebbbmnjh 13962: wdtlunhv 13963: xqnkebgb 13964: pbvieejo 13965: jauonhmy 13966: hcrhkiji 13967: rxctpoge 13968: ccvsgogs 13969: nfxlqjov 13970: hrldiruu 13971: usrlvdgt 13972: eglhuhkj 13973: wejwtfup 13974: faybpclq 13975: oioylrpm 13976: rwmwpykd 13977: ixfmsjkn 13978: nnilrufc 13979: adtcsrqq 13980: ycvmoaqr 13981: ddnkgise 13982: ddfbbidx 13983: etwvdtgq 13984: tjaxhsba 13985: pfkjreee 13986: vilpxjyt 13987: jpxoreqt 13988: lyikxqvh 13989: xmbjsfes 13990: cuwrmcta 13991: alqpvycm 13992: lhemyxyc 13993: djwkkvmc 13994: hbmlgcfr 13995: vasmgpga 13996: yjhtohns 13997: yttkvtia 13998: myyghwsl 13999: fjjtncit 14000: iuxpujjb 14001: ovbkiuyn 14002: tmpsdviu 14003: jmykquwk 14004: ivfrftol 14005: atvfuxdl 14006: krgsqbfn 14007: ohulmvvt 14008: qyloshic 14009: vevassxu 14010: yivfcaqw 14011: qjbtnntp 14012: cjmwrdmj 14013: lscxvknv 14014: vlogtvmg 14015: hnfmgmgn 14016: sminqlgv 14017: kurnksix 14018: uuqtkmdt 14019: bmroyidd 14020: uuebecqu 14021: qmgxhsie 14022: umesdtxu 14023: soekcoty 14024: laukftjf 14025: sdfuolro 14026: kangtgsf 14027: wgqcbiig 14028: swlbtxst 14029: qmvpktgg 14030: cdhjaxre 14031: oljunuik 14032: iaftpkap 14033: hwvtiasx 14034: ymeetsjn 14035: imueadhl 14036: klsnqeos 14037: ulrudjlr 14038: tjgxpftu 14039: cmcrurtu 14040: pkeawktl 14041: vwqoitjh 14042: ayujjiwy 14043: cxjhreen 14044: uocushch 14045: yumfdgdl 14046: ltjgcqao 14047: xmtlnihd 14048: augderal 14049: qnmjasmk 14050: hjnvwuet 14051: lgevbtin 14052: aqsapndi 14053: dgphqycd 14054: juueuqkl 14055: nxfgwnvy 14056: oxuvtplm 14057: tjfohpst 14058: ghrhcsdn 14059: gmhdfgqe 14060: wkwdkfet 14061: dytxjgjf 14062: ksegqpiw 14063: fgqwrpxo 14064: eqwianfm 14065: nyqpssfu 14066: xfumbebo 14067: laitvocu 14068: avmkvmme 14069: pbdnqtdl 14070: nhckaiue 14071: wngcleoo 14072: wxdescyg 14073: qqqtvnxj 14074: lgmdorkh 14075: qdpmpode 14076: mbuevrbe 14077: sqowtfms 14078: xssgvwjl 14079: uavvkhkx 14080: cknkjdnp 14081: fbdykqhy 14082: vmbseugm 14083: diysjemy 14084: etnlyoyw 14085: suenbbkq 14086: hlxfvnhp 14087: hthhslho 14088: lhkuhycl 14089: pfobgdwb 14090: jcyaxndp 14091: dbajfehy 14092: hurljsoq 14093: rkcwqbjt 14094: pllibwer 14095: ffftdsfk 14096: yegkhdfb 14097: hpyeycac 14098: fpeliqan 14099: jleurlur 14100: geavfubo 14101: cqfhyycu 14102: qrxifxbx 14103: etiyvvjt 14104: mjwhoirg 14105: koamlkko 14106: hxdxdnpq 14107: mueoemxf 14108: ptvpfryh 14109: wdiwwddf 14110: woveggfa 14111: lyogjdon 14112: knohqlqj 14113: kfghtvcs 14114: jkgemidg 14115: yjlijujo 14116: tiatcqbr 14117: sragoncg 14118: fckwegvq 14119: lidkimio 14120: bytttmil 14121: jdajqndy 14122: hhvdvyyj 14123: dnkupnpg 14124: fvkuslju 14125: swgsyrmf 14126: kpelyocp 14127: qhcipdor 14128: ucchqfbv 14129: eloqetgn 14130: owacuufx 14131: sxhbhhus 14132: lswstbpa 14133: gfemiyqg 14134: gsnonjnj 14135: jjfngpfv 14136: ekclsnbi 14137: tgsiujuj 14138: wbixtioj 14139: hedhrjfp 14140: vqirsqrh 14141: aqpdhaag 14142: qpouhbei 14143: uljsdkgq 14144: pkctxotw 14145: rdedcjdy 14146: hklqnxqw 14147: kojloxrb 14148: kvwrskfw 14149: apwfprqy 14150: eivldlia 14151: vfyegsug 14152: trvvitkn 14153: hmrxlyys 14154: huhnbhkf 14155: tmsjojna 14156: hvhvvgjc 14157: fsrbjwdv 14158: adnuherd 14159: sbeohaim 14160: fodoclep 14161: rbqdmedc 14162: ooaklhsf 14163: uvohyjqi 14164: diwxqjqd 14165: lbumfuua 14166: ytoomodl 14167: akseswcq 14168: qutsduig 14169: qobltycy 14170: oscvunbl 14171: bjofdnec 14172: cmjpgjub 14173: vqjeaolw 14174: rvelajlr 14175: rkfaupqb 14176: xmuhwsym 14177: nohklidq 14178: xhtlakhq 14179: gqldweqo 14180: bvqhkyum 14181: xtaxrbrl 14182: whyyubsw 14183: clmjrgyr 14184: lsgplygx 14185: iqjbqsyc 14186: ryobnoio 14187: ntomebmu 14188: ungjpkyo 14189: otrsqjcl 14190: nbqxikeo 14191: vbvwqhlu 14192: klpnpieh 14193: tvuoefkf 14194: xboekhho 14195: rfmksfgg 14196: jqoxusfb 14197: vweqvmwg 14198: juwesrhf 14199: xnufvtke 14200: hfmwnnar 14201: bbqwmcgd 14202: afnnjqjg 14203: dvsrvycx 14204: cgiytgyv 14205: kfgwmxlb 14206: cpsybkof 14207: ccnhwcwk 14208: nvnvqnkh 14209: qkeppdvr 14210: storpyfd 14211: whciojsb 14212: taciyxll 14213: vjvcdoih 14214: wpwtatqn 14215: qgtpjsaa 14216: jkwwxawr 14217: nycphlnk 14218: otwcqksr 14219: uqlcflrq 14220: gefbqjml 14221: dffltvov 14222: likdqpss 14223: breoouhn 14224: olkheiqr 14225: vhibcarl 14226: behnxuvh 14227: fmwbiyhk 14228: cubgnfqb 14229: bppopbyj 14230: lqjwksle 14231: cpceawgm 14232: xcjjrplj 14233: lptrdqem 14234: duqupwjn 14235: ukmpxmnn 14236: iiapcwrn 14237: kxuhckfu 14238: lawllixl 14239: qwwigbvt 14240: jalisfou 14241: kolxijec 14242: upmbhskj 14243: jldqvgyh 14244: vaibfyxx 14245: kfqfwlnx 14246: ecviwnch 14247: sdcilkbn 14248: euqusmmf 14249: asgtxyrj 14250: kutweitb 14251: bmdrlywh 14252: aqdhsbhh 14253: dwumqxlo 14254: punbgcle 14255: jmkbvvin 14256: yjvyieus 14257: ermvpeop 14258: lekcspkc 14259: gegriiaq 14260: alyvbbbl 14261: jrroxiis 14262: fmpbrpwk 14263: ungytjta 14264: anjsbwyj 14265: rqgyuwqw 14266: khvwxrhn 14267: kvlsnosx 14268: defmfiga 14269: okssioyb 14270: rljmeduo 14271: pkfkxniu 14272: khcyqjru 14273: oyjlrprr 14274: mhvstewv 14275: dxotlvcw 14276: iotdwsey 14277: pohvenuu 14278: hrdtfdab 14279: hmtlwrjh 14280: rfglsldy 14281: bdugurpx 14282: toouujqf 14283: dmjrhnrv 14284: irthcmnd 14285: ugfdorhr 14286: qdwyoldu 14287: kdghcvtp 14288: itlxmdts 14289: dqmmghtv 14290: umrstone 14291: hbautcuu 14292: fjaffgna 14293: cxswfnkm 14294: pfrsmkmr 14295: gsfkhedl 14296: ccajooqo 14297: qqbmblep 14298: harydmve 14299: xyoskofs 14300: sdkegynm 14301: mlbtujgi 14302: putlxmpm 14303: whxucomv 14304: lbdtngml 14305: tvcqyigh 14306: lgnxgaot 14307: cxcqxenc 14308: rsdoaojj 14309: sfokgjar 14310: isuervnu 14311: xukwujsi 14312: sdiqwcwk 14313: buwyhiuv 14314: pknrpsuj 14315: vdipidlc 14316: ewsakkda 14317: mtdfajnx 14318: igmaaxqw 14319: clbdfaor 14320: fonofxyk 14321: uqqijjyk 14322: jmqmkglk 14323: tvocxweu 14324: cmbuiued 14325: fvhmhqnu 14326: ustscure 14327: ciayrygp 14328: tdyfiiii 14329: mukkumvi 14330: jifrjqnw 14331: wvvnhwes 14332: swsutniv 14333: pllkugoa 14334: mouswioh 14335: rsxxqrbd 14336: vwkayxkh 14337: ovdjcwsn 14338: pomvqtcr 14339: gljxgija 14340: rkmfyrxe 14341: xpuhpshw 14342: phhhuqmn 14343: rgxthjmf 14344: slvjfhtt 14345: qewbrvml 14346: nexwbwjv 14347: nrofqfvp 14348: jqyvrutk 14349: jhemjqhe 14350: qjvxnaxw 14351: cbibyeot 14352: ddgpsvcy 14353: knfjherh 14354: trroawci 14355: oqwvltft 14356: pyuetmkk 14357: dmvdsfkc 14358: tajgenhf 14359: rtoecwhx 14360: bspuujvk 14361: emjrdsaw 14362: kkngylop 14363: hrffwneq 14364: acsmyhuv 14365: datiowlk 14366: iwiokttk 14367: ekupbyyr 14368: crddvmxl 14369: wknudaek 14370: spwplyae 14371: cqixlojb 14372: nattnvpu 14373: qosacsfd 14374: mtdtciyv 14375: ogpmgghy 14376: xjrnoveo 14377: difsajcu 14378: intfsawv 14379: gefppsng 14380: yryvkeiu 14381: nofviqpo 14382: tgabbcyq 14383: mukyawnh 14384: skrxkxyh 14385: jgaiexbc 14386: wwvxrxey 14387: ylswbjur 14388: fxyopfky 14389: oibgfdqg 14390: kwwovjoh 14391: ysqemxoi 14392: symleqpq 14393: bclvrbvh 14394: optfqcut 14395: wxviirxe 14396: wycnjilk 14397: edixmjub 14398: bncdonpx 14399: dnaqfplt 14400: kohifkvw 14401: vsmywnci 14402: fsbxtrgw 14403: otcicpmq 14404: ynrpsqqw 14405: fvbytivv 14406: xdghmdwr 14407: qabdhuyo 14408: rgkudlrc 14409: rgdfukaj 14410: uweshwbv 14411: ddgwudhv 14412: wprirlpm 14413: hocppsfe 14414: tfgpbhdv 14415: ldeoyupe 14416: cbwpgvvp 14417: nfgptsun 14418: tuuyjwpl 14419: bddpmfpn 14420: irwckrrl 14421: filfpkpb 14422: pijtxloy 14423: phgubeov 14424: nwsqucnv 14425: kndcbjpd 14426: hnnxokxj 14427: efrtmgkg 14428: guxafwnx 14429: ollegrxg 14430: xmgdroml 14431: wofdkjfw 14432: knyfepoo 14433: rqinqarb 14434: kjtfcwke 14435: rcunirlu 14436: eihqhcfx 14437: hgqjwgri 14438: rdpxyege 14439: pmerrpcm 14440: lvnuifmv 14441: kqrbhcbx 14442: afmuytkh 14443: vocymvxv 14444: mtfjgoad 14445: vvusrpgi 14446: dfiupjvi 14447: ebcaafep 14448: hcfugljq 14449: ijmsyval 14450: nvhekgwq 14451: rmofptnt 14452: iudjpmwo 14453: xrhkcyba 14454: qxbeyorr 14455: awxnofow 14456: visausob 14457: wguuiham 14458: cxkciyig 14459: wvudbrvg 14460: whfxougs 14461: uknoeuwc 14462: wsigbhgq 14463: vplrbnaj 14464: khxqgtmn 14465: nuuugmxp 14466: uuupxlvh 14467: dcwanvvg 14468: rvqsewjj 14469: hpvjekqj 14470: ptlpddmh 14471: pdhiuobi 14472: kqbrtgpb 14473: dcggdovt 14474: uxrgcmhp 14475: sgwcwtqa 14476: xbddphxi 14477: mybwqwue 14478: oebberyw 14479: binxeomj 14480: jhrxatvc 14481: tqfjixic 14482: pqcnwfkv 14483: hbqopuqs 14484: pmellukh 14485: lmlenhkn 14486: ngkqxhvi 14487: rkojdsec 14488: diwwudvw 14489: hlfrmrqd 14490: tatcoato 14491: xpvrxcok 14492: fenrhrcj 14493: agsxotnh 14494: rvknyqqj 14495: uiwenhpq 14496: aruymfhu 14497: eiddussw 14498: sskjudpu 14499: vsxngjva 14500: ycfclckc 14501: meoiwdpr 14502: gsyukflm 14503: agcjwsae 14504: xxvanjvx 14505: cqqiwqxn 14506: jucusbdk 14507: nbuhaheb 14508: roxexhuw 14509: lhpdqomy 14510: usmbwtqe 14511: fmgjybcp 14512: jlualsqc 14513: ifcvrfti 14514: lqhidcki 14515: nxoaeuln 14516: wstcjwkg 14517: fkecljgt 14518: ecqfqmgm 14519: kcxrctxr 14520: rbtwqrhh 14521: vjmnblah 14522: lgjkklkc 14523: pxckvcyq 14524: klcoitbd 14525: gyskpmjg 14526: tesyiovb 14527: wsslwjpn 14528: lvpufoch 14529: onirjpum 14530: cbhloktf 14531: qqwmnqbx 14532: cfliwvbr 14533: lohewrmh 14534: ykvljyaa 14535: ujcxqhtb 14536: jdlsunip 14537: xiqcfrlx 14538: qbbybfmo 14539: xxpkmssn 14540: poovekou 14541: hgjtgmwf 14542: lgrmuiln 14543: emmujnuj 14544: kvjlmuhg 14545: yxjhfeui 14546: lusenfew 14547: hqpxdxyk 14548: dolmptek 14549: hhhxdxpd 14550: wqtbcuhr 14551: fofdqjom 14552: edxlqpku 14553: eoqqlwef 14554: vdammcjv 14555: hrpnjxfi 14556: esvoggmt 14557: ixolkrmx 14558: akjkhuei 14559: bhbpsqqv 14560: quxexjkf 14561: sklkidaf 14562: ikmqpscy 14563: ayopfise 14564: urtyvlel 14565: xhtmfucr 14566: idavafcb 14567: tacqluym 14568: ikoccwpq 14569: tqucfcaw 14570: angitgrh 14571: xcecihvd 14572: ghvaclnl 14573: gbywraqq 14574: qrayujpu 14575: ttecabcl 14576: gjgpuirl 14577: mlmjktgk 14578: oghmlvsn 14579: dtdopogi 14580: shgaisvj 14581: ftisevkf 14582: kxsfmhtm 14583: oaqqahie 14584: dtfapieh 14585: kecrrshn 14586: saloyqhx 14587: qwmhbbuq 14588: dbksotym 14589: arxkrqdd 14590: dwxurden 14591: spagefvs 14592: vngaqlpt 14593: hequbueh 14594: xbsyiday 14595: tmawxkri 14596: uftgacmp 14597: bucttcds 14598: pfqmvfyo 14599: ixftmwsc 14600: movburoo 14601: gjlwskir 14602: vvbpqafg 14603: xserrerx 14604: wyiqkepp 14605: tjqeloxc 14606: oueyplnm 14607: kuffdrys 14608: goqyffjb 14609: qpoytduk 14610: ggtnefmi 14611: qfbjhify 14612: jxhrulur 14613: vnugylwt 14614: jogfkgnu 14615: piyjjxrl 14616: yxrrsnjl 14617: ghcgbhtt 14618: kxxptdgm 14619: hgkpvtmo 14620: itldjabg 14621: cqwnhqdy 14622: hcevqaow 14623: qkymktcv 14624: ugwnksnr 14625: epblpxia 14626: ywwfjtmg 14627: lvphnobx 14628: yxvyrxac 14629: bawsccgg 14630: yylmygvr 14631: hoddusqr 14632: ionfychu 14633: dbwlltot 14634: hbrahifa 14635: jcygddjn 14636: mphdqerw 14637: cgdtldet 14638: qfujkjhc 14639: viarqmwq 14640: dnrqfchi 14641: kvxbqqds 14642: pfwectjw 14643: vqbhkewc 14644: tokpbyim 14645: vvowbckh 14646: utswtoju 14647: ptljmqtb 14648: oxmhlrrp 14649: jeilfffg 14650: rkdypfus 14651: rcfndmsp 14652: rtbcrrti 14653: rionrots 14654: bcygkily 14655: bqleucqu 14656: anmpkfsn 14657: ynnkpmsm 14658: sjlgmaoa 14659: xwehwxhl 14660: afhqtsvy 14661: gogovbbc 14662: csfhwiiw 14663: ojcptbil 14664: cpdogpwg 14665: wfjgibac 14666: vjlldswf 14667: ovmiwstt 14668: mlvwnvcp 14669: glftuofe 14670: bmewegxp 14671: snkhaeuy 14672: irfqmsvy 14673: goqvyqnd 14674: mgxbnmxt 14675: okglhbjo 14676: vlodhtkl 14677: giqywpah 14678: lenxhpug 14679: trxvgqwf 14680: vhhxtqmt 14681: proqrchy 14682: bhbrmkvx 14683: pwvidxip 14684: ohherrys 14685: uakxrysm 14686: dtbexqdx 14687: kcwuejmp 14688: axafdedw 14689: vghrvcgk 14690: klpdruum 14691: ynffgcid 14692: wlubpaeu 14693: ilibsmnq 14694: ojvagfqb 14695: nnekdoom 14696: aggrgkng 14697: esnaywbn 14698: qrcujyrc 14699: sybiybyi 14700: mqfxyfua 14701: umxkitjy 14702: lyyuqxgq 14703: plkjxpng 14704: rjlcjbse 14705: vvhyxexi 14706: fwfqpdem 14707: smaxinpx 14708: ewxocdcw 14709: qskqomgx 14710: iolbcnvm 14711: cqbgdckd 14712: nfovhpas 14713: xoebpddl 14714: qocxtxcv 14715: kbqnprmq 14716: wytgbjnc 14717: wdsbmgad 14718: wgjtaomb 14719: shufesnx 14720: bxlaadlh 14721: bwpqcdmd 14722: abbrwgcp 14723: mynyehrr 14724: xvuhlxux 14725: wkxftpew 14726: mnnqlsih 14727: khdcamtv 14728: orfmvbli 14729: hdkwjlbb 14730: pbfylsdl 14731: gucexlfh 14732: xlnlexwp 14733: acjcqtqm 14734: trbawdbe 14735: wrctibcq 14736: wrlbgksk 14737: pnhfpglc 14738: arqywhln 14739: fmaojfbp 14740: yxgjibmh 14741: prvwsvhq 14742: qalmkhvp 14743: gulfhgim 14744: jlgbltfi 14745: lenahevn 14746: dcnlcruv 14747: tiekeypg 14748: ydcsauyq 14749: knyegvoh 14750: dymuyutm 14751: cdmxgtvq 14752: scigolsi 14753: hccveguf 14754: efhachhm 14755: radvswmi 14756: ijuwpjvh 14757: mkcudakk 14758: oxxdmptr 14759: trujbkox 14760: owimytuk 14761: owexermk 14762: eyslbkni 14763: eawpbdpc 14764: obkbvsjx 14765: earohyxv 14766: plxtnwcb 14767: wfeqhpcl 14768: wfnkqkdq 14769: awmsywct 14770: awowgmvi 14771: jmicxoik 14772: ufwxprpm 14773: xpfatets 14774: tvbbjtxr 14775: dqgwtpdm 14776: ifxoawej 14777: jpspbush 14778: okjhsnvd 14779: iwwiaxcb 14780: qnhvpeis 14781: ndvioqrl 14782: qgbtjcay 14783: ljcybvvm 14784: yhgyleoy 14785: pmyqjdwn 14786: sruknxwn 14787: lofqmcjx 14788: dfnrejaq 14789: nouxeidl 14790: owbkvweo 14791: xyrqtejo 14792: ortktlkw 14793: tlijqfcd 14794: hicjdcff 14795: oixoagbo 14796: vajqvnup 14797: spgdyucr 14798: pibrwkox 14799: vgswtvlt 14800: prcsdytr 14801: pkhdqpxv 14802: sjayvvly 14803: stnqgkxs 14804: nvadjxnh 14805: mfnyswhc 14806: crqynosa 14807: sixsteeu 14808: gmulxqpr 14809: kqdpqcvs 14810: ascyuimj 14811: xcnjlaqi 14812: xxtjmuip 14813: wjptvigl 14814: hvcvuavp 14815: fydhcdvt 14816: svprknxt 14817: kfruhuhh 14818: felsweuj 14819: hsfodihb 14820: rpevsltm 14821: ghffecrc 14822: umqedesg 14823: pweshwtp 14824: shdnxjaj 14825: fyrstnwx 14826: alqgmmni 14827: loqcijwb 14828: gptdkwgd 14829: iimhfwyu 14830: xfmgaylj 14831: yujyhdjp 14832: jyaaauvk 14833: gdriydea 14834: tcctkexr 14835: owpxhvwj 14836: ichnbqeh 14837: qsgddkig 14838: cqjxptlw 14839: cxdshnvx 14840: ynnlviys 14841: qevtiype 14842: fqkwbmmp 14843: rtentnme 14844: iscrfdls 14845: ggedvxry 14846: imsvcxfm 14847: yrmpbqmv 14848: vbscjaky 14849: tkfrbraf 14850: qjvrnsqo 14851: pgyvjhgd 14852: srcuchti 14853: myqjvmff 14854: pxuaunpr 14855: tcdxwpbs 14856: altreqry 14857: evjqciro 14858: lscomakb 14859: ladcqfhg 14860: yicwndhr 14861: qxsaogsd 14862: wnbdtqgm 14863: mruxiisu 14864: ybxjhogq 14865: ukvgnmwx 14866: ofivdxks 14867: lcfrulql 14868: hdohyrwb 14869: iqgqjtny 14870: kurjxiip 14871: ltphpotf 14872: vnujgcja 14873: tfduxkfi 14874: nxcrwakv 14875: ydbivgyj 14876: fccpwgwb 14877: yytivtyk 14878: pbrckpwu 14879: etbcrbbq 14880: jqhjifna 14881: trpyuqcr 14882: qofmekml 14883: urpmcyww 14884: jxxnvhjg 14885: ljwwpoac 14886: fxobpkfy 14887: hqaeqxmn 14888: gmwltxwv 14889: fiuojtsi 14890: eurauvty 14891: xbyfyabu 14892: kmdrlufe 14893: tmqbndhx 14894: mqrqagow 14895: knyioqwy 14896: jsruqgbn 14897: lwkavdaw 14898: ybkmevug 14899: sxcownuc 14900: frubsccj 14901: arlairir 14902: bsyfpojd 14903: ixtetwos 14904: sifglqfu 14905: jqoafrub 14906: jwctxdvg 14907: cmusuqlf 14908: eangabwv 14909: octtdcbu 14910: wsgklfxn 14911: cgjksyqk 14912: xthjqxeh 14913: cjgieuyi 14914: qvvpxbwv 14915: gklqjjpw 14916: refgyhct 14917: vtiilexs 14918: ewclgyyk 14919: qyvtktfg 14920: emuekrug 14921: jrcwlyuw 14922: nqairmee 14923: yocrkobx 14924: ujsdrosg 14925: hcdejsrx 14926: nccmwtyw 14927: bcbtfxyu 14928: mbkybuyq 14929: xmbljflk 14930: cdncvpuy 14931: mhxbaprj 14932: ebvryqlh 14933: gjwaxtwg 14934: oeshsxih 14935: jufgxink 14936: ijtsucrb 14937: axjylswn 14938: qiffnkmp 14939: qbagikkd 14940: qkripejc 14941: kgbeooxv 14942: pfdbhmkw 14943: riflbnuv 14944: xmvcgnuj 14945: kcsndaeg 14946: hyxfkhhh 14947: wajaccgt 14948: pugfrhur 14949: wburmdpq 14950: wnoderqq 14951: xcricela 14952: yhvofckd 14953: jemynncl 14954: cjfdlaqe 14955: boohvyst 14956: opnusmdf 14957: eshcmphe 14958: ltrprfpt 14959: opxchrfv 14960: mfyxhfpc 14961: lytbwweh 14962: grvupipl 14963: cydhseda 14964: ghpowiwq 14965: lvmwopgy 14966: nswitkki 14967: gstmjunm 14968: ntqjcwgt 14969: qwsxujar 14970: beajxwhy 14971: ngjpxrpp 14972: tqfvmhur 14973: wdfqnsrw 14974: kgmhslol 14975: ugppglon 14976: lafecake 14977: nshxswgq 14978: obtfnhmv 14979: xjvfcthf 14980: efvrcnyf 14981: evnknxkh 14982: phmhwulw 14983: bbrtkfws 14984: juukcovx 14985: rhpycilg 14986: jxmmclaf 14987: elvppyhn 14988: aqimbwko 14989: wjoyshjh 14990: sjhthvla 14991: majwvyjs 14992: wrsgsblp 14993: jfdfjoyn 14994: pfebkuxd 14995: xxmcqqyb 14996: gutpugms 14997: hahhkokf 14998: vvkjebfk 14999: xnoemdra 15000: yeykwcmn 15001: fshiquym 15002: onsuhmvm 15003: tqtnifwt 15004: wnhowkdo 15005: pifydpxx 15006: iqewdsom 15007: ditrraku 15008: shebkbsb 15009: itrgnsmc 15010: nnwxskee 15011: dhcmkltc 15012: pfjkiuig 15013: aajuuclu 15014: tyrvcwty 15015: ekgsiuun 15016: mbbngoxs 15017: yiocdffm 15018: pytutfjo 15019: apoghbjo 15020: jmmgohwt 15021: xfniipjt 15022: wghcglnf 15023: dnocvumx 15024: lgfigsom 15025: wsyrguvc 15026: sqxvands 15027: siayegfy 15028: yrchtqul 15029: kkcmlenp 15030: lhoyphtk 15031: chdenqkx 15032: shhidpum 15033: dosxxtnt 15034: vxhyaxac 15035: tdvovmhm 15036: wmmrhgiy 15037: eumwdmll 15038: uqjeajwx 15039: tkwbgcqc 15040: tbafsgyl 15041: nxdipfgy 15042: arvqtqii 15043: hblseofq 15044: ohaepvqi 15045: mjbistto 15046: ypvnnava 15047: txswstyb 15048: tikkltar 15049: wjemhwtd 15050: rktkumwi 15051: vlfxgjrg 15052: mimnnspf 15053: kmwyxobo 15054: valokgmj 15055: dvdshjqf 15056: lckwmnkg 15057: dqtsrogp 15058: eagodyts 15059: tjwkaxrj 15060: lftfcyoe 15061: nsydnurw 15062: awgkuktr 15063: insirfss 15064: ketegdid 15065: fcadnrkf 15066: pddqejwp 15067: mvfyjwit 15068: hoheuwkb 15069: dwsfddyg 15070: vdmircqw 15071: yufgdnrx 15072: exekmura 15073: khuufphk 15074: alkkixll 15075: qlmefrfu 15076: kvjyvcxw 15077: gpnmirgo 15078: lvmuajyl 15079: wqligwsc 15080: bxpshqkm 15081: sseovxer 15082: namewetq 15083: eetupskg 15084: lyrlsfot 15085: yvhbyyfy 15086: fqiyljrj 15087: axavihqs 15088: cvktwjxg 15089: pmiclgtx 15090: kbdhfxvo 15091: wnjmuusm 15092: apgvslnd 15093: qbvgfkxa 15094: qlssoqnv 15095: frwktvem 15096: dfvilnov 15097: pdymqyyn 15098: yupfihoa 15099: mbkxmwwk 15100: wcksxjlc 15101: nyygtexf 15102: gqehkikv 15103: ufovjgnk 15104: rlyilvnn 15105: floyhise 15106: lptgpvqj 15107: dybwfauk 15108: vbhrkkvk 15109: kmaiewjs 15110: tqqfircq 15111: fhnppupl 15112: ceojyjxo 15113: dpldmqnr 15114: ebhksrnn 15115: doxrjkkc 15116: jgsvbtoi 15117: ehtvklnf 15118: nigyedrr 15119: fhwjhxdu 15120: btddvgvd 15121: qoelfakt 15122: vnxsymel 15123: jrkfkxif 15124: ikuqutwj 15125: fujywmgx 15126: heyhtdda 15127: ofrgikim 15128: tvdnidbq 15129: hdocwrlc 15130: nhvtjyst 15131: lcfxmlxw 15132: mddgrtva 15133: aivgxsdr 15134: ubuymyqp 15135: sgqgbrqq 15136: xfjlaopg 15137: qnbehuyp 15138: kihoxkjv 15139: dmcldjfj 15140: wuanqoyf 15141: pltyourf 15142: swgommgr 15143: yjfddahh 15144: ntpedawa 15145: cpktithv 15146: jxgomtiw 15147: psibhbaf 15148: btpqoyqt 15149: wpojnysl 15150: fvffgllm 15151: dvaqwhbm 15152: wmuwpmsy 15153: hghtehlk 15154: rptieysf 15155: opjtqwhn 15156: belnsgpt 15157: umhrolrc 15158: oncupmkn 15159: hidrihdy 15160: unyigdmb 15161: qimyxvfe 15162: cupgjmsj 15163: accplrol 15164: vuumpbwq 15165: kdpreckt 15166: ubysjqmn 15167: wsmaianc 15168: gxrrqjuu 15169: euusuwos 15170: hnrcxluw 15171: yafgsbji 15172: ixxykusd 15173: hyioxgqw 15174: acfuxqfx 15175: icwifbcl 15176: batiohis 15177: pxrrpfcp 15178: rteqhqkw 15179: sbywiqce 15180: mcwcqkyg 15181: olyfjuos 15182: fwksgrdi 15183: kxboinou 15184: agphodwv 15185: sykbekll 15186: lcayosiv 15187: wbqmcatj 15188: rveyowed 15189: yugyatoi 15190: edmmifom 15191: mrxblhoq 15192: ohdlasuo 15193: rjtoybvo 15194: gmcadqqj 15195: povmaswi 15196: ncfjqxdf 15197: fqfmftjt 15198: denrutgk 15199: thawadgt 15200: hdxbepla 15201: ockvctgg 15202: uajugpgl 15203: mmwlgruy 15204: fkpdbqbh 15205: dkdbhyyl 15206: ofedfcxf 15207: fytxeqxw 15208: qaielyun 15209: rxrmijsw 15210: jlorcfyc 15211: ubxipekf 15212: otccqdyj 15213: vvxasegu 15214: gvseepje 15215: bpfvpdjr 15216: cxhjoyfw 15217: tnlsdliq 15218: rxgorfvg 15219: ttuhxgai 15220: erlybbuj 15221: giqaqhxo 15222: byhcsixu 15223: nsdxnlqc 15224: ocdaipfi 15225: tkvekxef 15226: bdehpttw 15227: bdytxvfr 15228: qvnvhvsj 15229: nyopchsl 15230: wyofcqls 15231: ouhwiays 15232: csvcmgcm 15233: pfsdxtbd 15234: hmmaluol 15235: ejtksipc 15236: fwveihsg 15237: yigqmrwl 15238: yhoxgqbm 15239: qpkehmty 15240: chwgtnnj 15241: xsnvvwwy 15242: ooyqkvsc 15243: epmunsgm 15244: nrtsdgmf 15245: qdfwgdeh 15246: kaogbhkv 15247: dnpbymux 15248: vufvuiit 15249: ghcvlvhq 15250: gjyxrmpk 15251: sxptwnpv 15252: cxayogpo 15253: dvlmdmuj 15254: vgudoksb 15255: ysiuouuu 15256: eknmtwoy 15257: rblgwodr 15258: urfuvnyc 15259: cnnahewq 15260: rtvvmaos 15261: fkgmegtr 15262: kcvlvibc 15263: luudcxvo 15264: dcodwcjh 15265: itfiwvmn 15266: ikqgxsfw 15267: aaxlnlqw 15268: jvybmrpf 15269: eplgptpr 15270: dnwknovu 15271: beitwwvg 15272: qwjcdshy 15273: uptmmppb 15274: tajeckpj 15275: kycpgfrf 15276: mpynoecc 15277: tdnnddka 15278: sfybaoel 15279: uphtkenr 15280: uquuxfth 15281: pgqpmgby 15282: bcoymokm 15283: pboatxtf 15284: dhmbsabn 15285: exogbrfu 15286: gqgcmwcs 15287: afwsmhgo 15288: ceemhgcb 15289: woxbuxxq 15290: jpklkvlw 15291: hhcsptik 15292: ivlemnnd 15293: nvrccmgm 15294: kbbcdktd 15295: kkoapaxr 15296: lmdtwbah 15297: jfqeivxw 15298: rkrtqerf 15299: rtpebrgq 15300: vjttfkup 15301: lnjjpwfv 15302: kldsedtj 15303: ygmrigaa 15304: aoedixft 15305: hxsgtccr 15306: lbwqapus 15307: ulhrrmvi 15308: cgrdsgwc 15309: mnwfifda 15310: qppekgwx 15311: krqwsobi 15312: qbirbgub 15313: awqeeyou 15314: komuclkn 15315: dlxuvbgd 15316: bqsvmcin 15317: htpsbbeq 15318: addaphjm 15319: hbuvuhbf 15320: jrdvsulu 15321: bhiyusae 15322: bkpsrtvt 15323: tpxjbssx 15324: fmkxfavg 15325: haulgeym 15326: swivetjc 15327: tsylojql 15328: jkowbuta 15329: joromabn 15330: fuhuhflg 15331: bqjhngld 15332: gjkyhxnk 15333: vrqgquaq 15334: pdadbwjp 15335: wofrgymj 15336: jtcfvgxk 15337: hdpjmqvl 15338: wkjwslbn 15339: koainntn 15340: onevrtjl 15341: hardvxtl 15342: dmluenfw 15343: sbuobrjb 15344: gohbshwm 15345: fiegqbwg 15346: uayykocv 15347: kihucjkk 15348: kwwmokvb 15349: ealbxhei 15350: ejgmpfdm 15351: pcxvtbpn 15352: jvypxdcb 15353: pnrwacri 15354: ldeyfyae 15355: bytcehou 15356: foytvqhr 15357: lmoylxpt 15358: iupsxnsp 15359: rewkllgg 15360: mvenjbwo 15361: kvlimepx 15362: hqttrany 15363: ydshjdry 15364: ckxmrgbl 15365: stsowakv 15366: qogxqrdx 15367: fxghqpok 15368: ubmpwbfg 15369: cefrultd 15370: pwopjnqc 15371: qonjrefb 15372: yenkscge 15373: xfjqoayi 15374: wqbkddmx 15375: cvsybmxw 15376: koapmekr 15377: doesdowk 15378: aofsddew 15379: gujarhys 15380: kipvbxwp 15381: xffinwpj 15382: nowebkvc 15383: ocikilop 15384: edepqhyp 15385: hoowadiy 15386: kxxgihva 15387: yntpnptl 15388: jrletjha 15389: jhyxqvyt 15390: ihxuttcd 15391: stbrdwlf 15392: litlamyh 15393: qaknvvnl 15394: cdfwobdg 15395: lcgqagdo 15396: udsjuqlm 15397: qdtubbqt 15398: vtfstbow 15399: xyntjwul 15400: jvxtjogn 15401: fnrnyiil 15402: lrruamby 15403: eomhdutu 15404: oqosgvhk 15405: ecdhnbva 15406: avyhqpkp 15407: njkbioli 15408: xqjigkqv 15409: vvintqxw 15410: ebgayexw 15411: knranbow 15412: okjlslhq 15413: jmawbtur 15414: ubhaiiel 15415: qsxvynvg 15416: psfwioop 15417: wobjwhja 15418: nhaqxrcj 15419: mqjoajxb 15420: oiodjyie 15421: keilcjol 15422: bsqtxonq 15423: lbhbdijs 15424: cacbwrey 15425: etmxehnn 15426: rdqnrlpu 15427: btwffegt 15428: cjupkxna 15429: vhmsbgpd 15430: vmnmkauq 15431: qncryyno 15432: xtqbkuxx 15433: legxslni 15434: iodmawmx 15435: mhrjlpja 15436: ixkhkfon 15437: tbhfippd 15438: srdjgwbv 15439: xqwvnpbi 15440: vppuysmp 15441: akhelnlt 15442: ijrdckxr 15443: xexckjgu 15444: dcobhchs 15445: kxmonaui 15446: mvsgjjeq 15447: ptsimvuw 15448: iskribvb 15449: rkwcnixp 15450: yxyacnha 15451: kmutpgcq 15452: pcaygerr 15453: lkwokqbd 15454: rrjfmekl 15455: hamikcsg 15456: voplupnd 15457: ljumfnbn 15458: xdblkqfy 15459: maosfivc 15460: nmvpofoc 15461: rngebwps 15462: qythdddy 15463: wisasyng 15464: cuaacngi 15465: qapxecib 15466: trugmvos 15467: coslempl 15468: twngoave 15469: wdgmqgwh 15470: oehalcay 15471: jbijikdm 15472: cgphjxyx 15473: jguiwoto 15474: bekptfna 15475: xkqcjnhu 15476: pcrqgqjk 15477: aohxsbge 15478: bxdjychr 15479: cwhpxodg 15480: xpjppgvd 15481: ggehsgxk 15482: hgwioeaa 15483: xliaqdnb 15484: jdrpyhby 15485: tudjahqr 15486: agrxdale 15487: yratppqr 15488: xjgfjvju 15489: nyquvkmn 15490: kexftdhe 15491: hfjhsuow 15492: jlvedcrb 15493: mwwvcvxs 15494: onjysjrq 15495: yceljtov 15496: gwxlgdwy 15497: gufjvros 15498: pxwxvrkn 15499: bpjmtxld 15500: jkclmskh 15501: qofepofw 15502: itejqvmj 15503: lvrodgdm 15504: tgqblhsj 15505: jjidhpbw 15506: btgiotne 15507: sevmsxpr 15508: naiksxvf 15509: eqmpvpoy 15510: bxtcycxy 15511: xmiqsrpb 15512: pqqoskvg 15513: gmabvmpg 15514: popxripj 15515: ietoxbgi 15516: xdrfwihu 15517: ycpxijre 15518: fpuabepb 15519: fadlyqiv 15520: utcmehvo 15521: pcgdrcxf 15522: sltnugrt 15523: dwoxsxhf 15524: mfvreaig 15525: hevebgfg 15526: njiewlwq 15527: qlxlndwk 15528: xlyecpve 15529: urbmdkpa 15530: evyfogpv 15531: urjwjnla 15532: txhacffx 15533: kealvmuu 15534: ytadolus 15535: teomnjgv 15536: henjiuxm 15537: vnmrksln 15538: jyspsjwj 15539: qmejlluv 15540: gqqmaiuy 15541: vdmywuew 15542: arhgawhw 15543: bycexieb 15544: mnuuvwar 15545: cnnakpkc 15546: kofwssyc 15547: effejqxg 15548: awmwxlkp 15549: xskslkih 15550: uuebxtkd 15551: prpjrlli 15552: qykmnskh 15553: fegdjglo 15554: sbagnhjv 15555: rexdpgyx 15556: mvrexgxq 15557: kdxhhaaw 15558: bvwspyly 15559: tjbydgyo 15560: oymmceyq 15561: ciemukbi 15562: eqyjsoej 15563: rewnebmx 15564: fkvfpkfk 15565: eywxqfuq 15566: glnaskds 15567: sgrcudhd 15568: pkmopuec 15569: rfudenca 15570: rhqumnhx 15571: ibgjegee 15572: pawmmoak 15573: rkntilpa 15574: pofqoouk 15575: wqymuwmc 15576: xtvelhme 15577: ofyroiqo 15578: soiyowgo 15579: mngukpmh 15580: btqqwqrr 15581: hxrxdaon 15582: wqstrcam 15583: mbuxjarr 15584: yewkpsox 15585: odfsyjql 15586: dsxdwfso 15587: fnkflswp 15588: fvhsnxwu 15589: duxifkwp 15590: vhteogqi 15591: oduagymg 15592: rawcckjx 15593: xmmwfchr 15594: mwnnknaf 15595: cfphhyfw 15596: egghqofm 15597: agmhooyr 15598: ujhoxxvp 15599: krmjcium 15600: uixqwrps 15601: ftlgraid 15602: kaftppmj 15603: hpouxjne 15604: aogwiwqu 15605: bgrauspr 15606: eunvcwpg 15607: ymnnvvts 15608: jrxvlbhm 15609: njnsmqwo 15610: nvwigcvv 15611: cmenwfmh 15612: xeaswagc 15613: oghbagfk 15614: gsxvtntt 15615: bsiiytmb 15616: gfvnalkl 15617: joraccao 15618: jfyablnx 15619: lubstvjm 15620: bkggbmbq 15621: qfqlwdgf 15622: dqhswmtd 15623: kwqkhhlq 15624: tiiopahk 15625: xxfakwvk 15626: dnishkfb 15627: ltofnhmr 15628: jgoreqlf 15629: rvusrchi 15630: mkkpmuhs 15631: qrwxovkf 15632: shqnnxen 15633: wepdblyi 15634: jkelwdbq 15635: nxcanvui 15636: fyvbsjhn 15637: blqfxddj 15638: veqrjfqi 15639: arrhgwri 15640: cnqyclsi 15641: uuranree 15642: drgxljel 15643: saiyrkeg 15644: sgvvvrnb 15645: aaaaafcj 15646: jutoddqb 15647: jrvnkbeo 15648: xbmclnlp 15649: ovlruies 15650: mwgqback 15651: pbngkeux 15652: pbhatvwb 15653: axoviesh 15654: hkqgbash 15655: lxdclshn 15656: xpjbosww 15657: dvrymjvx 15658: niovttbo 15659: itbtjija 15660: jdfmdmro 15661: xnaraxwr 15662: dypyipcb 15663: xymldnhu 15664: pxhydhxo 15665: cmtlavnk 15666: cfytkpio 15667: jbvejpjn 15668: tefagwxm 15669: gifbramr 15670: xlxyaqhn 15671: nxfhtcdm 15672: fjxwvycx 15673: mclqdbtb 15674: fsvnoexs 15675: yxpacrry 15676: diekxxta 15677: sddkhimx 15678: oplislfv 15679: ohpnysdh 15680: annlgxlb 15681: gpytkkpw 15682: tsuicwaw 15683: kjidyrav 15684: mdkcvfch 15685: vmjiligi 15686: nonfpyuy 15687: nowkrdog 15688: ylyykygv 15689: sihjfswt 15690: vnpmajmx 15691: pqppbhhh 15692: ydtdqtqt 15693: vobjornd 15694: flmsdcrf 15695: hpwouldf 15696: hmbwsxsd 15697: ilemiljf 15698: rpatrvxb 15699: ydymkhnw 15700: lkvwafff 15701: okgtwwfi 15702: maixinhj 15703: wqtpxmnv 15704: mepmxunn 15705: krdjwcow 15706: vjuhngpi 15707: fqwjcoke 15708: yqfsjaqy 15709: mcuiuakx 15710: xocmbpvn 15711: jjoikttj 15712: jgesnjrh 15713: dfsvcjdy 15714: dewblbqm 15715: foixrvnd 15716: qwussxjq 15717: qrqejwky 15718: ggeounbq 15719: hpycducq 15720: iapnicto 15721: nfyrhwjj 15722: mpqmqpqj 15723: wddbapua 15724: giqneexh 15725: kiqmiqlj 15726: pqykuuqx 15727: ddjrcugu 15728: pyruxviw 15729: xrjwviaf 15730: hrsjaqhg 15731: xhmhpwnw 15732: pbotsivq 15733: yqbigirq 15734: aytjbveu 15735: kwqorvmx 15736: ipoaqgyc 15737: wfmswtwe 15738: nkdyorma 15739: eclncfew 15740: btdvdmkq 15741: ucyslgja 15742: ltedfybi 15743: berppise 15744: jsafeeav 15745: ebetquac 15746: gebmithi 15747: festevev 15748: tguiijjn 15749: vjbumsnq 15750: xaghrlpk 15751: gomhrcdq 15752: pwgyoiun 15753: bdhpbich 15754: spofosck 15755: sguyisod 15756: kxwnrqkm 15757: aokjoubv 15758: ykryhdfh 15759: aebjhyio 15760: boqyyjfx 15761: lipxnrvf 15762: wicreeit 15763: cnvufqfx 15764: hdeduity 15765: nvniaudt 15766: ctwpvxku 15767: evwjocmm 15768: nmdipxfn 15769: eyulenqk 15770: vffuavqj 15771: xgsaoasi 15772: vowtxqqt 15773: ckqkawax 15774: kevvcgtd 15775: rflisyuk 15776: jeslafab 15777: ufknlmre 15778: tkakxahe 15779: hkaugyxm 15780: bjexdlme 15781: psuwiwkn 15782: dahfgofd 15783: rlwwfedk 15784: ooqhukhc 15785: ptshxhig 15786: jkdcckva 15787: kkmxcjvd 15788: tnqpltvu 15789: bigwqotn 15790: exanxgdm 15791: cbkymjyb 15792: wwwfcmal 15793: klehjjff 15794: swylyvgw 15795: enffiimh 15796: texnnyke 15797: jwfbprqa 15798: kmqhsuix 15799: kmfucpdw 15800: esjpbmvy 15801: lxcyhoej 15802: rcpoxqef 15803: daionlep 15804: ojbyqrko 15805: mtguwxtd 15806: xhubtqit 15807: mhwfqtwp 15808: wiuvaeey 15809: nnkqfdxa 15810: cdrpbgli 15811: cuisfegm 15812: hpyrfvki 15813: gunfhglj 15814: vgcsbcro 15815: qvimngpl 15816: pybangrs 15817: psrqikek 15818: wjvgdfnu 15819: hdfihbnt 15820: rhomeism 15821: jigqhbcu 15822: wqguywli 15823: bcuvlvgd 15824: roohunpf 15825: obqjkvtb 15826: hihebuel 15827: elbmbooh 15828: nqyogrxg 15829: odmhrodw 15830: stfjbrvh 15831: sglalwbq 15832: xygquxri 15833: jipebyab 15834: vxanymyb 15835: lloivojo 15836: evijwajs 15837: pnbgmblm 15838: rltsplgh 15839: vfkgioct 15840: ihrjlwrm 15841: ieolshbl 15842: jeanyear 15843: wbcjpgdb 15844: prkofpgm 15845: sbmwwoji 15846: fhmsktsd 15847: hbesnoyd 15848: iuuvvcak 15849: wlxwhfxl 15850: tudjdrgw 15851: edcpxtpn 15852: liwpbgln 15853: vgiolyhv 15854: ylmitnfe 15855: ysjadgxq 15856: bytdxkyo 15857: tovfjeqk 15858: sshfrqhk 15859: flgqrbuc 15860: tcvfiach 15861: kbmsdvvf 15862: bpnuyivb 15863: pxmxquss 15864: hralfewo 15865: cmmuthnc 15866: kkcrgugx 15867: euitoqnf 15868: ojrrpfah 15869: gwvlmrar 15870: vtlnhtmy 15871: obvdlkxv 15872: rjayrboy 15873: tamdayld 15874: ctietprh 15875: smccokws 15876: ghxjpjvx 15877: qocfriyh 15878: samibcjx 15879: bwvhudua 15880: wjuycsdp 15881: kjxwhxkh 15882: qlriucke 15883: rxvixyvf 15884: ekuqpnrv 15885: oipypfur 15886: qeaarfvw 15887: dqwtagec 15888: qrjraxbr 15889: mnjnuorf 15890: gwbcrcpy 15891: xtqsgnvf 15892: rlhtjlkq 15893: uumsxsiu 15894: imdimtvk 15895: jbuyqmgm 15896: pladambt 15897: tnxsldtq 15898: gqugkbmx 15899: nycdcafb 15900: wrkgktii 15901: ihrcblur 15902: iikulkfb 15903: jbxfbjpj 15904: bvgojslf 15905: piuansdr 15906: qlvwudbw 15907: tskvpmjq 15908: ipevuxic 15909: wvcgrmoq 15910: liopyexm 15911: ilucmqqw 15912: wvgducob 15913: hdogpply 15914: lmxycdck 15915: ovylgsdr 15916: xjtplmsc 15917: xwxpwsdn 15918: uvrnxqss 15919: shrvggga 15920: hlkpfdab 15921: ybmwnwem 15922: nlpvftci 15923: knwitxcx 15924: syhtgqtf 15925: vnryhloo 15926: thxqscqt 15927: elncueij 15928: indylqhe 15929: hpyrsmif 15930: noihwlqv 15931: mcettsfq 15932: lnetaphr 15933: ktrvbjql 15934: nvsdpwxn 15935: fcrnvict 15936: gpgkffqt 15937: ykwxaavc 15938: vrlkpriw 15939: uhemiplt 15940: vrbkpksx 15941: mattesid 15942: vkclcdmn 15943: kevqwvtl 15944: kmkstoik 15945: gohujvuj 15946: umdefiqe 15947: dpuowwwo 15948: kbeljvsp 15949: vdycwblu 15950: rtbqvdnh 15951: iaewihxv 15952: gyftyidu 15953: awpjebll 15954: hssdxgsu 15955: yxmnaudc 15956: wfcyeuek 15957: mnwyhbou 15958: fjwfdrfu 15959: mxekvvad 15960: rkfgslsx 15961: mqlrekjp 15962: nopxbqah 15963: tusdybrn 15964: soctbuwd 15965: idthmahw 15966: pmdjygwy 15967: oykyxmle 15968: hwnoabem 15969: ggnrpygw 15970: uhyhdyao 15971: nvncaium 15972: tfhmeuhl 15973: csvhdhnm 15974: adhuojuf 15975: pfsyfnyu 15976: gqxclfux 15977: txfsokba 15978: sdftpxbd 15979: hpuowjwj 15980: mogoxian 15981: kqtgyeak 15982: sybkiwwu 15983: unkwkfit 15984: arbgcapc 15985: keqntftg 15986: lvpddecy 15987: wysyumis 15988: wjcqgqee 15989: kquktynb 15990: ydxiqrva 15991: dvdobhtp 15992: kgsokass 15993: dmfybjtu 15994: iofcmmit 15995: qfymphve 15996: dmktwgbn 15997: njhewwkg 15998: mqthcscg 15999: flajrkrm 16000: enpcxrus 16001: gmnkeoow 16002: cainkyrr 16003: nltrnddh 16004: hftadhyg 16005: rbrbtbin 16006: nqdtyefe 16007: ovmrhpbq 16008: ggrjivvl 16009: vytmvqrp 16010: kgewvamo 16011: qeboigho 16012: sgknsgmg 16013: jgpcxots 16014: vrnrokju 16015: fsuhiceu 16016: dathgblg 16017: tumlajyp 16018: ccrumawm 16019: gtdtqrha 16020: jnpnocyj 16021: koxdpmws 16022: hspricam 16023: fpgxdrkj 16024: lkftfjvc 16025: hyqkljgy 16026: whohqgmx 16027: vitarhde 16028: sigrivsn 16029: hmubdbkr 16030: tflsahkt 16031: bgvmlrap 16032: gylrovcy 16033: ijtyidbc 16034: jreuduqx 16035: cgjserjf 16036: qlecvffq 16037: bhrvxnnl 16038: stayrtqa 16039: ohfkdxfq 16040: mmpuhxjw 16041: mgrmikky 16042: xiyfmfuy 16043: cewyucaj 16044: qkfidhrk 16045: ebsnmnow 16046: uiywilwa 16047: rdfsclwy 16048: vogjaooa 16049: qlhmymkm 16050: pwchqsvs 16051: alxewobq 16052: wdkjxgly 16053: dqewtvnd 16054: fhsixyjf 16055: plcgajrk 16056: oudrxlha 16057: xjpprrmd 16058: dsfdnyww 16059: sciijukv 16060: imqsykeu 16061: qdtmxeqf 16062: yocwppft 16063: jxvskyym 16064: mvhxebxc 16065: fggchmht 16066: qsslxlnj 16067: tmhohdic 16068: lxvhialu 16069: edgmkslu 16070: aioougev 16071: mdfhfwhx 16072: efgltsop 16073: kghowave 16074: yfyhojmx 16075: ognlnrso 16076: sjugwvax 16077: uqbkogjd 16078: eexiwpsv 16079: mcbtemrc 16080: vheisetq 16081: upanoahl 16082: retmtoxw 16083: ndcxlkvw 16084: ocsccacn 16085: shsgytqk 16086: myegiccv 16087: tymcwyfe 16088: rbmbtqej 16089: mfaqddvd 16090: sgouiusf 16091: lfistxfb 16092: wymkrqcg 16093: gubhhneq 16094: mqpyddwd 16095: ludsqsbl 16096: ffpcmlvx 16097: ftuoyexb 16098: pcpwfpxm 16099: ibvjmxfr 16100: krmwfrrf 16101: qlnepcia 16102: vfmfavhv 16103: hlobihbp 16104: eblbxblo 16105: sjdehjnn 16106: fravbmsl 16107: obqubusk 16108: rfosarbw 16109: cngqfpxi 16110: gopxvhcr 16111: nscaixee 16112: vugpnjiy 16113: rebqmoxp 16114: ibrxdyxa 16115: rsdqhlsc 16116: lmyxdmmv 16117: iatnxtqf 16118: asfcpexp 16119: rafhgkrw 16120: heohenco 16121: jcrwxixp 16122: havqaome 16123: haavgpvv 16124: drhxnuwb 16125: ptwqcnsu 16126: bqcejlnc 16127: oaptmbqr 16128: enpnxegj 16129: glscrsqi 16130: ojpgwftq 16131: gsuafkkv 16132: ahbkdice 16133: augdogvt 16134: rcwqvpxl 16135: wqgwlidj 16136: ltwxghhf 16137: pyvjbxsy 16138: qtceyhnj 16139: wxhcfbcy 16140: jnanwhxs 16141: nwyhxyqo 16142: euobyjgx 16143: sebvvyuo 16144: nevnbvom 16145: dlcefaak 16146: tteghlqq 16147: yygkojjq 16148: sehvkyvd 16149: urgdegho 16150: ctxveggw 16151: ovwmeuhy 16152: xldaciyy 16153: jqwripjo 16154: okgkyjfm 16155: okyfvtka 16156: rndvjsef 16157: assryqak 16158: vrqiknvx 16159: awpstrlu 16160: skvsekep 16161: ryxwrhmm 16162: ddauorlv 16163: tqolworp 16164: dxvetahp 16165: xbqkkeso 16166: dwbdhkbp 16167: ehlcgvkb 16168: ivijjsnv 16169: eciiokbe 16170: icyvonrt 16171: ggkamssb 16172: lamwokph 16173: pgysettp 16174: bkfmmcia 16175: crdyqjtr 16176: ksxynlsn 16177: ejusnxnh 16178: cfsbqnep 16179: hwavhlem 16180: yxhjmgrg 16181: jbrromch 16182: jnjxuaoh 16183: cjcdmhek 16184: rttjlsye 16185: smihyral 16186: oiwpyumg 16187: vuinycrq 16188: xqtvehjn 16189: mwgsmjmg 16190: cfrdaihr 16191: hnjntoyy 16192: gmjmklox 16193: tipbrjms 16194: iwcjoadr 16195: anqywqhx 16196: sjxwuogu 16197: smxlppva 16198: ibcmpkef 16199: xhodmywb 16200: eypijccb 16201: yboivdvq 16202: oxhgifmq 16203: ovrvibxs 16204: aiihjves 16205: tweujgbm 16206: tqxfsixm 16207: rukcdfik 16208: mfeusefc 16209: ylwleegy 16210: riymhwik 16211: aatodcbm 16212: bbmankyq 16213: wolktpbh 16214: rvmkcgxc 16215: sqhxvqgq 16216: qtxyoswh 16217: ldrnxqbb 16218: yvchnlyv 16219: hwvajpsp 16220: oqyqotpd 16221: ivphwtog 16222: qqobdmuw 16223: nrsxqapf 16224: ilboiwos 16225: hrhvwnjm 16226: yyhapnuh 16227: rkuvffku 16228: mdufdupd 16229: mtlwxpcw 16230: jvnfdrkx 16231: enobrfdi 16232: xckqcftt 16233: ptboriea 16234: uaxlkpjh 16235: huencxjb 16236: pfyqvhlp 16237: kjsyupht 16238: nsyrmpfi 16239: vgaqixcj 16240: ajkswiwk 16241: ttgnubit 16242: qpqxxsah 16243: ocluflkl 16244: drgynfkt 16245: boxdulfl 16246: chcugtti 16247: vxaepgnb 16248: qeqamgxs 16249: adbgxqam 16250: yqncacvn 16251: ggryplee 16252: ylksilgs 16253: qyqgdbgh 16254: tdlarlna 16255: geyraxpi 16256: mbmqldbl 16257: txoseogt 16258: qwfovoek 16259: hduknqej 16260: ilnjimti 16261: aufimvsa 16262: qgesuemp 16263: mtoymlso 16264: pbjbdofk 16265: cxrsctqh 16266: vllptuxk 16267: werkehyg 16268: hsuitruw 16269: mdteluui 16270: cnkgfwjv 16271: qubltjoe 16272: bnlcrjxh 16273: qndlwslr 16274: sisheiwt 16275: xvtgwbir 16276: cdoswlil 16277: jwivrhag 16278: abhprquv 16279: rlqbggtq 16280: mgtyfjkj 16281: iucgsagv 16282: wawpgovs 16283: paynxmbd 16284: sdkvwywi 16285: ycgqmevy 16286: owlenwyf 16287: flrkygny 16288: brqlciwk 16289: xhhuorom 16290: ahdnierq 16291: wygwhtmy 16292: agkcnaci 16293: nhnvkdmt 16294: hyyvqvmm 16295: cnwffrki 16296: hliocorm 16297: bflgkcrq 16298: msgkxuhd 16299: vuxyhcrx 16300: uilrephl 16301: icuifutp 16302: bvshatrj 16303: tddmjggu 16304: xrewapnb 16305: rqodkftg 16306: iiiefnsi 16307: quopouhw 16308: hlpqksdp 16309: wuqtbsad 16310: ftpgjexb 16311: jvqnpxmr 16312: rslxdwuq 16313: rwgemqhm 16314: epipittv 16315: llagqton 16316: mhdqnopu 16317: orqjdulp 16318: cnfjmmxs 16319: lqamghny 16320: gplnttiw 16321: qlskeave 16322: afijphxv 16323: jgwyhddl 16324: mqktgwov 16325: mxkerywh 16326: lgtssqhj 16327: xkgihagl 16328: ukpvpsuv 16329: pmccefxi 16330: dkytltgg 16331: fgnuggyo 16332: llhbpmoj 16333: ikprbyxe 16334: kmllwyyc 16335: hswvtphx 16336: osdqjoiq 16337: tjhbjdej 16338: catqbqiy 16339: hsdtsyrf 16340: ktgaylkn 16341: xxvttrac 16342: cfamfrrd 16343: ubjyuomf 16344: hculteka 16345: swimreki 16346: ewfiacuv 16347: idnbpyww 16348: ikifktss 16349: iqsllkbr 16350: wkukmxra 16351: wxinswkn 16352: uctthjuf 16353: uavpmovd 16354: xemwyurg 16355: cipslusd 16356: omtxmkak 16357: tawkgpci 16358: pxqwoxgf 16359: kvtjuyao 16360: lbcharst 16361: tvcwyqml 16362: ganwtubj 16363: qastbxkw 16364: qbvkfyhc 16365: htebwkrp 16366: iedvjbgp 16367: vyxjkrap 16368: jbsmkxan 16369: rxyshgka 16370: pkrvrfxu 16371: augbritd 16372: lhsheycq 16373: ojjrtpub 16374: ybelyyxi 16375: nhdvfsuj 16376: aknopitl 16377: aryoruvv 16378: ujqxppby 16379: wivrokpy 16380: vlphysmm 16381: fotmjjxc 16382: kbqnkgky 16383: ywhqgent libvmod-redis-21.0/src/tests/assets/tls-ca-certificate.crt000066400000000000000000000035371476735432100236300ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIFQzCCAyugAwIBAgIJAKETN42WmkeXMA0GCSqGSIb3DQEBCwUAMDgxFjAUBgNV BAoMDWxpYnZtb2QtcmVkaXMxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0 eTAeFw0yMDA1MTQwOTA5NThaFw0zMDA1MTIwOTA5NThaMDgxFjAUBgNVBAoMDWxp YnZtb2QtcmVkaXMxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTCCAiIw DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMkronFeqBVGzOTG1aT7qodwXGFq AlhwHiP+UGMQsIqSfi234eHE9mgYnJI4PRsktdE0hp7VL8d9nDJh/YLpWm7XdJ2d J5gmDrkKVSGVAb0HY3jAKIn8tR7h6xkB+9ymiYRwUrrf1Rqb/uaiUP9yy+DVy3IY Mvsun9XEKdqgSlt46AGEN1GQvR7JksUkfl1UgCO5XYBRlxtukL9X6XQQUQrcdcVN AABKYUqQRftPCAeuEyZNG5MjWyLD47lAVqhg8YhskITQR4X71zVXo0fl5DwViQzI iaaM/BgFOc1h6KPO0QYCvXiaoABCHMRJqDDoOSdmCvSECJSW8yRJoZymupKmdKcP 4JXXDlSMZGiHEQcxV8mPE3L5CZLH7NzTtOgPUPpt9ljNQ+Ilhy0qE5fMDyNG32lq UNSigsq9/lyW+mKPjsuL9MTiOHYXTaqcwZUdNYQfo1uzVxcriXH9iRghGn7fuFQ9 UW0yG3ec8kAJs58oyaDB72I4vI7n7PYb5FTK/mNiKVRBFbpveavWqNt9mp+RBxBN pOk6Yk4sQALPe/fCSSUsrovZxonm6bhG4dR2rs56q6Y/13Nox5fbkhD/ziyn7zU1 cnsr71WgsHKJkrLYY5rcyXBuhkIV8B9Y/X02M7FaUup8+H5fQr+aY4eaP6lkOfun y2ZdtufF2j67TSMjAgMBAAGjUDBOMB0GA1UdDgQWBBQNl++oS2E319WipurTvGKp q3sr2jAfBgNVHSMEGDAWgBQNl++oS2E319WipurTvGKpq3sr2jAMBgNVHRMEBTAD AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQBKX+ZjGOpTz5yfF80YgOJsAhZ8mKmKHB6E RrdRqAKgdrxxDq7iB4vbeyyONBHd6wpUP46h2UYw8eI3RdFRlVwGI7tmNFz7221F k3gPYDgP6HFtWOwTosoA9A93HGmfWeakYipxyDdLC+lozf+1H/qVPzFUZkc7Y5Wd 8IpRveKTq4JhaHrrkbWRBTHiMd3+XeAcF6XNoLykmBi/k3ji6SS5Ua4xss2lPDgr mhnh2J3CCJ36xZ2aHmMNHb3oHKUz5TdRDxLL5bedXi8PGRvtb0KFjD1zjBWZi+n6 Wf/Cp77a70p80UVzHV7eFsWQuJ4OaSh9bBPyJxXsk6CDD99mN076n88WuEMl0Vjv UJdw3QQI0GHNRiPMjNjpN2J8C4+J1l9zVssomHHS854TFGY6omoCI1Q9iRNlPaXY eolc94ktXbebVzpK5iwyBM/GVPXZQRWT2Fc5JnKBfQzqlwquSsA0Ctqi0lgrsNxq 1mkduO5ayibrEYnGftLgMSLh08mVaZaJLBO1kyDWfyouFMB5ujEbvXqz4oER395k xjEqo2oLcOfSG/HnHHpRCzqx6fg1tImGOZ1mSqQG9bGXgT6cQk0Qtj9zgomXBAvG QIliykO6rPhm1ayAwyspKK5LY9426euXbfpBjfe6GMvD73FkBGBIo3athLOmg4W4 RHst3wAbkA== -----END CERTIFICATE----- libvmod-redis-21.0/src/tests/assets/tls-ca-certificate.key000066400000000000000000000062531476735432100236260ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIJKQIBAAKCAgEAySuicV6oFUbM5MbVpPuqh3BcYWoCWHAeI/5QYxCwipJ+Lbfh 4cT2aBickjg9GyS10TSGntUvx32cMmH9gulabtd0nZ0nmCYOuQpVIZUBvQdjeMAo ify1HuHrGQH73KaJhHBSut/VGpv+5qJQ/3LL4NXLchgy+y6f1cQp2qBKW3joAYQ3 UZC9HsmSxSR+XVSAI7ldgFGXG26Qv1fpdBBRCtx1xU0AAEphSpBF+08IB64TJk0b kyNbIsPjuUBWqGDxiGyQhNBHhfvXNVejR+XkPBWJDMiJpoz8GAU5zWHoo87RBgK9 eJqgAEIcxEmoMOg5J2YK9IQIlJbzJEmhnKa6kqZ0pw/gldcOVIxkaIcRBzFXyY8T cvkJksfs3NO06A9Q+m32WM1D4iWHLSoTl8wPI0bfaWpQ1KKCyr3+XJb6Yo+Oy4v0 xOI4dhdNqpzBlR01hB+jW7NXFyuJcf2JGCEaft+4VD1RbTIbd5zyQAmznyjJoMHv Yji8jufs9hvkVMr+Y2IpVEEVum95q9ao232an5EHEE2k6TpiTixAAs9798JJJSyu i9nGiebpuEbh1Hauznqrpj/Xc2jHl9uSEP/OLKfvNTVyeyvvVaCwcomSsthjmtzJ cG6GQhXwH1j9fTYzsVpS6nz4fl9Cv5pjh5o/qWQ5+6fLZl2258XaPrtNIyMCAwEA AQKCAgEAgaDCXfc2q+8hXFHbnSIl8nwuqv7aYA5u/ZaESjGY8NIQyHjy7r4yYUVq rrXaekEff50vGe4ZiZyhJ74I03B2u3HOTTnVJ69uUUIdNTSFGD9Ik6iO9suGEk5V ZZnnp3kQp+yRAqX09d6LVCZHtzNLuKdLH0wEneKfT+nFZoFfKK4yIbgGxWJU2x/c mXg4jP9ESsDJRURN8HlAgGuvnQBemHcS1H4XgBhttNReo997NyeuY0HQgPGJak97 0AVrUbiWKuh5/3sOe4GaXV8JcezrMuRVmY0nVdEHKJtFcdijRdqgyhS97pcEfuYb D0i/PjSFj6Orb4Ac31KdfkaMAxtUoMHTlWcYwWey44pHkTylggLtAgDir+A85TeG bWTqyV0RdTA0tZsM98OvBDYHg+smQ1+I8Odr2hq9AaVRqI0uHQ1payQY/RwhPzEG 9Md55wXRqITSfHBfM7QcfUAFw5DB3+7SvUhCMprQUUMzvDPN0Yq7CSWB+RIC4tma D8ez1Up1SdhYkw21r0aKavizJ68iANXPJ6ASREBJyQHk98X2ew3tyionsGAT+agK 5jXKEaKJPCax1kaKN0xW1liaIzS8aTU54R/OAXaxctVWRlmQ39z3t+7K7wf3hCUD iE7vLs9qXtm/oTMKjfWMcV5RlUsEwMCDraxponu4X1F+s4abXdECggEBAPJuxSY1 0eztXFfNx4PmWByiM8CSkr1+X8jS0QHQL8qxY0CePZbwOx5KJvCz001NHDAJkFci mqWe8d43G3qfPvXkHvGBzjndV/XdQTBcDJMAMs/NN4Ul1RH2PqS8y1tijt2OFW+v dXYQUcpGplMS82vFKHE+048mpW2lLEbwCnfVizglWZkMW7rJh3JQqAasdw+b5J8R dYc1PjnS5C9NdnI5NJUwfGqn6hYaKk6KSJLW0qZncPg7XrvTCoktZpehclu1d5Qk 1pKJfUQf/JdaKm2nxeYNWTvjGaLqfX1GEWxD9v0gaeyAVT9U6KhtDvuK2yoLoNhK NBiOXUzMPO3NZRcCggEBANRtt8DR72ahE8S8rWCs3koY/CJyRh4mecMgRbp+LC/y ZX6jApC+pH2KWjOILWzQLF858RQSu2J1d5nEFzqmaoRTUR4wRhNimjTyJAKrpNbU DmJOuEVaAbzAecv7mTMLdMZp2P3EuOOo0itv0fjQF5Qn4pqOD428oZEXqNf5ul+0 V51cjJedufNGQN1aryP9yU7yNkuSRiJdorkajoBIGuLRtNIEKVtUvFTWsbIRsOOY jverOHdQojJX9yHSO24OpfGRM6XXzSNNwepGprXPrNawZ9HZF61j7iQxc+rTgIFX p2zucajmoRRrvh9fssy9uvRU5WNl/yJ6ceXtyYPKkdUCggEBAI24EUnH9oLhMrUl VzeU5PdAHq65QEzD3myASKwdroJ39gRlPK3Km1SWlnLpPGGY7RxrytQVJ4AgDVYQ suCYzO5jP2+AqTSMXwocICqL9NHOMOXnGkicmBTa9T3KG7q9P7TmhUN3t1ugKJ/t cvdnQaNDauPgjT3GorgY8Ww6kHQDAlJ9CwZ8AfeMLcC2w7K7CRK32Arg4up6Rnj4 /mlkiBQ3urRn1qNmq2HmQ8sL7Wbha9zY5WJHGpcDxMnyH2IOf9J6n3+blU+uTesQ I9G6ZMkbZYWZUgu/M1JYb6lW14KJrI3GcAVP9AWEtkkXD8YeIwZOK+WkYxXjy0jE r+13v1sCggEAaGq+BgOrX5ERvITZ3ElcwqNhXDU7jhpvg6BbZf4bDj5h8UuDOU7c X/EfwXDQk0oIZY5/l9RVU2JWNbkTifq/JOgnWWV1LJYtIpVbagyg7BA0OdJj9YL2 k6cwtzmm5lZdQiJJTQPjtdQH6t3+IgV3cZXhZwMpVgxAhqdQkUjpeZ2V633Qhb47 5v7DZ4rpyBE5YJriYWc3HjFUiRQqs5e9z3wxG4J8Ka6PHEyj79mOT3Fv5QG+sbdq 4sAmc/N4zvJYU1OCRaS76vyPsu6jh37bgHQZtCa34rzaE+RTDDyGUA2b+ImESPeE ehszywwpQUaJnQwV7TP3oyT404J8qVFrOQKCAQBxoBfTELeqW6BrKuW/cSuwlleT 3cqD4tFEs+i9Zam7QLarW4gRumcjvM6/f11AEvTDxsOnHPlc0eOu15omJ8A7UONR /9VNJtpe6XJHF60F5uY4Vus1GBpwoPNaAjtv8Y5bgzV5ypKABOuWiB+vRAaTp3Qk n17HvNUmdpgEsQfkbWHyxChvmbVfQYMJ2iDQtkKeLnIVfJ3j9ITM5cj79BE50van OMgTeVRPrD2ys8vtxteFa8Cgg0sdvTLOyfI9ih5+iGTR/swN0GTsVze6e8gFqYu5 Z6gweSmndRCPRgZkDJV4FVsROcvPaU+9luiJezY2b7vpCuyybo10OkzUR3v2 -----END RSA PRIVATE KEY----- libvmod-redis-21.0/src/tests/assets/tls-certificate.crt000066400000000000000000000025671476735432100232510ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIID3TCCAcUCCQDS8vC3eKnWPTANBgkqhkiG9w0BAQsFADA4MRYwFAYDVQQKDA1s aWJ2bW9kLXJlZGlzMR4wHAYDVQQDDBVDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN MjAwNTE0MDkwOTU4WhcNMzAwNTEyMDkwOTU4WjApMRYwFAYDVQQKDA1saWJ2bW9k LXJlZGlzMQ8wDQYDVQQDDAZTZXJ2ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQC8dWT0rX1RtQFs7abaraAdXfhi0xGGz1hlxz41Y7HYPPHe9QZTMQuo zO+IQ3id4w71m2cBIr6xxQ9iDPJPclo+Pt/r2eEvQnyz0Ey47+I3ZFlJLvluB+xd Ytg4uPCr/IvVHL5r6fN6D9SJ+Tq9I47O52MfgYkkURMGVD1gVKF/gmwOlM1pxjlZ 0zwaZwpugv4T7UFIY9k4HcUuF92kJheBrW32Kk/GgoJ5JkPQlcmyqvs7HfeIRAM8 c//IyPEq6EzgtR7P5ctEiWi18sIRw4DbAhyLHg2jH0JznyEAJnoqA7nB3ySc3ldX 3PY0KRdvUm2lyxTmiVLDUl3vVLCy2IS/AgMBAAEwDQYJKoZIhvcNAQELBQADggIB AEVJXtAP5VuDWlihut8tashLgCNUf5us3Y1Hc71bvkNG/9OYUNx5PyjliPvunTpW Zy880BrO//ld2COeCMUSqGb+ZMdVVGRR06SEOCb57nqjPrAJBiG4IZKjhbzfFAgQ Xzfci5c0PIHFNOe+f7K9KdV0GXO7GHMHoVadoRf5L0KhKCoFzCnVfnksYLeqK0rQ nErp/pD+mij9tOj75ggKug990LP8Pva1sQ+u/5yzM16lblw0faTXllzGy3SyBsNr fMjkT57FSSHJWROtODIvJibLsBKo1LwZ56lKjVrQNrzcdlXFaP0tHlZyQdH+A7qX 1bDB9f+pBHCOHNaWNQHho3xhw8cnGhb02hNQXMGAC8p8wWUCBplf06IzkXXcQTXO GLc3O6N8dElqVNlhGj9c7SxV69vInMadho6u0q5vj5gMp3k+58CxMyvLq+kByj98 APGurxbei7Jd7Nl0F/m0PzPDXoSq+49wtZr/Xrw3g5AGqamIrTmIHZ4kdybTm1j5 Ts4HMI0yYm3d1798C2kRlGeued72k6n34fKobBhI3YzEgv48DdqTAwNNMhL6ELed c/7saFpJ7GYUtuywVsijJFra1/qkHcqnY0D9VZQTQAmbgzJBLzB4821g63IkGCUy 2DgfhEw362qxgVU/Br6rZvOzW5gu/iaAUg7thDIllw0U -----END CERTIFICATE----- libvmod-redis-21.0/src/tests/assets/tls-certificate.key000066400000000000000000000032171476735432100232420ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpQIBAAKCAQEAvHVk9K19UbUBbO2m2q2gHV34YtMRhs9YZcc+NWOx2Dzx3vUG UzELqMzviEN4neMO9ZtnASK+scUPYgzyT3JaPj7f69nhL0J8s9BMuO/iN2RZSS75 bgfsXWLYOLjwq/yL1Ry+a+nzeg/Uifk6vSOOzudjH4GJJFETBlQ9YFShf4JsDpTN acY5WdM8GmcKboL+E+1BSGPZOB3FLhfdpCYXga1t9ipPxoKCeSZD0JXJsqr7Ox33 iEQDPHP/yMjxKuhM4LUez+XLRIlotfLCEcOA2wIcix4Nox9Cc58hACZ6KgO5wd8k nN5XV9z2NCkXb1JtpcsU5olSw1Jd71SwstiEvwIDAQABAoIBAHg2OeuJLsMLvpkJ DsG2tseExYfkMu3XHP/vE9NigHL6jR43FY3DXziRYMl+oFW2HDi2pAGpdBJZLPLS Z04eF0pVOOhs1qMaugjI+eeNvLKwo/N2r0xsaW04O8wSzBIoydlquFyFovVdW6mW /Mzg/ZslJalXK2+q94O2AGCOG2YFZl1Qjm3XPawH7PXGT4gPmjUtYATTN3OguRpV d98/WK8jXkitLBmQR6nGNoeBxAeBsHh7VWllJIzB4O0Z3WiASMMqH8SqlA1q6Gxx e0cn+IYwJBgl0Njus/sxdHHSzoYwtR8lJ36phbYngZusYLc056sTCvvUhXsQIxgt 3hdwUUECgYEA7igENfDS0tYEquxe1oAIegXgOPDhkZvVke63WITOaewbhw48qq9S 35A/JVoTKqwzouplEdwZkf6a0DDrmNM0NCc3XkRsk8qTuFyyVWRqkpmtLpF2qR5/ y7HTekV/V7Rl1ZSDi4f9/TM8THU54i83ljRLnnV4ZptPZR1fWSP/RWcCgYEAypQl FWNPrVXLhgxt02GWTdeTdIxmG8ViTsLzKN5vUQBedAXdZldpC7Zh0FyLH7cwYeEy Tv9o2Ci39cQijad/q0I0w0VtW0nbff2HnAXHprc/dS/yu+Z79vQf3kOo0plJXMSs 9H++NBRUriKxAxx0Th9+4vyxL90eo21/VZ1olukCgYEAvAtmv7ymiokoaFl4zL+N cePf1rYENbepG7A0nrVGUoZ2ed448sC6nAHGilSkG6aaowGWylJS8l7pmId4D1R8 vM1WP52hadSjbQfsW9aM+7JR9xouanzFhW2kwL/NO9AaNFkuwOahGuLwsqJBESId LwGdz8GLTuFFAF7/4V+1+PMCgYEAvqjZkhyrE9eIurwd7XGOVesMRAgT3hVS5hAD bTaUjCcNvqL6cmTYYAaiXsmKwynVpnmdsM4f7jm8kdmsL6gyt4uTPymrt9x2cUjZ hhXGh3k2h2O+T+yoRZAUIkuJq9RLQL12jpNf/4IXBOFvuh7gs9pewOHVHdg+CtB2 pKyGkGkCgYEAgviuigal+e0paZCxkVRnDm7sClG+Clg6KLh6p8vhNOoxe2GddesY dyNlUT324jflEtf2KBkYPLJ5u0i/DBvnMuI7UlVgSvjqPuMcyZS9kNFt+JKIdHjg RaV4Mj4uQOR3Q8wax/5n/xtiR3Fdt76XkKPa/MmetTvNp+0mR3Hg14U= -----END RSA PRIVATE KEY----- libvmod-redis-21.0/src/tests/clustered.ASK-reply-messages.vtc000066400000000000000000000152111476735432100242240ustar00rootroot00000000000000varnishtest "Tests handling of ASK reply messages" server s1 { rxreq txresp } -repeat 1 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=cluster, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=true, max_connections=32, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=16); db.add_server("${redis_master2_ip}:${redis_master2_port}", cluster); db.add_server("${redis_master3_ip}:${redis_master3_port}", cluster); new master1 = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); new master2 = redis.db( location="${redis_master2_ip}:${redis_master2_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); } sub vcl_deliver { # Set key in master1. db.command("SET"); db.push("${redis_key_in_master1}"); db.push("hello"); db.execute(true); if (db.reply_is_status()) { set resp.http.Reply-1 = db.get_status_reply(); } # Migrate key from master1 to master2. call migrate; # Get the key (should internally handle the ASK redirection). db.command("GET"); db.push("${redis_key_in_master1}"); db.execute(true); if (db.reply_is_string()) { set resp.http.Reply-2 = db.get_string_reply(); } # Stats. set resp.http.db-stats = db.stats(); set resp.http.db-servers-total = db.counter("servers.total"); set resp.http.db-connections-total = db.counter("connections.total"); set resp.http.db-commands-total = db.counter("commands.total"); set resp.http.db-cluster-discoveries-total = db.counter("cluster.discoveries.total"); set resp.http.db-cluster-replies-moved = db.counter("cluster.replies.moved"); set resp.http.db-cluster-replies-ask = db.counter("cluster.replies.ask"); } sub migrate { # Get the key's containing slot. master1.command("CLUSTER"); master1.push("KEYSLOT"); master1.push("${redis_key_in_master1}"); master1.execute(true); if (master1.reply_is_integer()) { set resp.http.Migration-Slot = master1.get_integer_reply(); } # Get the ID for the original node (master1). master1.command("CLUSTER"); master1.push("NODES"); master1.execute(true); if (master1.reply_is_string()) { set resp.http.Migration-NodeOrig = regsub(master1.get_reply(), "(?s)^(?:.+\n)?([0-9a-f]+) ${redis_master1_ip}:${redis_master1_port}(?:@\d+)? .*$", "\1"); if (resp.http.Migration-NodeOrig !~ "[0-9a-f]+") { unset resp.http.Migration-NodeOrig; } } # Get the ID for the destination node (master2). master1.command("CLUSTER"); master1.push("NODES"); master1.execute(true); if (master1.reply_is_string()) { set resp.http.Migration-NodeDest = regsub(master1.get_reply(), "(?s)^(?:.+\n)?([0-9a-f]+) ${redis_master2_ip}:${redis_master2_port}(?:@\d+)? .*$", "\1"); if (resp.http.Migration-NodeDest !~ "[0-9a-f]+") { unset resp.http.Migration-NodeDest; } } # Mark the destination node as IMPORTING. master2.command("CLUSTER"); master2.push("SETSLOT"); master2.push(resp.http.Migration-Slot); master2.push("IMPORTING"); master2.push(resp.http.Migration-NodeOrig); master2.execute(true); if (master2.reply_is_status()) { set resp.http.Migration-Reply-4 = master2.get_status_reply(); } # Mark the original node as MIGRATING. master1.command("CLUSTER"); master1.push("SETSLOT"); master1.push(resp.http.Migration-Slot); master1.push("MIGRATING"); master1.push(resp.http.Migration-NodeDest); master1.execute(true); if (master1.reply_is_status()) { set resp.http.Migration-Reply-5 = master1.get_status_reply(); } # Migrate key. master1.command("MIGRATE"); master1.push("${redis_master2_ip}"); master1.push("${redis_master2_port}"); master1.push("${redis_key_in_master1}"); master1.push("0"); master1.push("0"); master1.execute(true); if (master1.reply_is_status()) { set resp.http.Migration-Reply-6 = master1.get_status_reply(); } # Check that the original node replies with an ASK redirection. master1.command("GET"); master1.push("${redis_key_in_master1}"); master1.execute(true); if (master1.reply_is_error()) { if (master1.get_error_reply() ~ "^ASK ") { set resp.http.Migration-Reply-7 = "ASK"; } } } } -start client c1 { txreq rxresp expect resp.http.Reply-1 == "OK" expect resp.http.Migration-Slot != expect resp.http.Migration-NodeOrig != expect resp.http.Migration-NodeDest != expect resp.http.Migration-Reply-4 == "OK" expect resp.http.Migration-Reply-5 == "OK" expect resp.http.Migration-Reply-6 == "OK" expect resp.http.Migration-Reply-7 == "ASK" expect resp.http.Reply-2 == "hello" expect resp.http.db-servers-total == "9" expect resp.http.db-connections-total == "2" expect resp.http.db-commands-total == "3" expect resp.http.db-cluster-discoveries-total == "1" expect resp.http.db-cluster-replies-moved == "0" expect resp.http.db-cluster-replies-ask == "1" } -run varnish v1 -expect client_req == 1 libvmod-redis-21.0/src/tests/clustered.MOVED-reply-messages.vtc000066400000000000000000000170071476735432100244650ustar00rootroot00000000000000varnishtest "Tests handling of MOVED reply messages" server s1 { rxreq txresp } -repeat 1 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=cluster, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=true, max_connections=32, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=16); db.add_server("${redis_master2_ip}:${redis_master2_port}", cluster); db.add_server("${redis_master3_ip}:${redis_master3_port}", cluster); new master1 = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); new master2 = redis.db( location="${redis_master2_ip}:${redis_master2_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); } sub vcl_deliver { # Set key in master1. db.command("SET"); db.push("${redis_key_in_master1}"); db.push("hello"); db.execute(true); if (db.reply_is_status()) { set resp.http.Reply-1 = db.get_status_reply(); } # Migrate key from master1 to master2. call migrate; # Get the key (should internally handle the MOVED redirection). db.command("GET"); db.push("${redis_key_in_master1}"); db.execute(true); if (db.reply_is_string()) { set resp.http.Reply-2 = db.get_string_reply(); } # Stats. set resp.http.db-stats = db.stats(); set resp.http.db-servers-total = db.counter("servers.total"); set resp.http.db-connections-total = db.counter("connections.total"); set resp.http.db-commands-total = db.counter("commands.total"); set resp.http.db-cluster-discoveries-total = db.counter("cluster.discoveries.total"); set resp.http.db-cluster-replies-moved = db.counter("cluster.replies.moved"); set resp.http.db-cluster-replies-ask = db.counter("cluster.replies.ask"); } sub migrate { # Get the key's containing slot. master1.command("CLUSTER"); master1.push("KEYSLOT"); master1.push("${redis_key_in_master1}"); master1.execute(true); if (master1.reply_is_integer()) { set resp.http.Migration-Slot = master1.get_integer_reply(); } # Get the ID for the original node (master1). master1.command("CLUSTER"); master1.push("NODES"); master1.execute(true); if (master1.reply_is_string()) { set resp.http.Migration-NodeOrig = regsub(master1.get_reply(), "(?s)^(?:.+\n)?([0-9a-f]+) ${redis_master1_ip}:${redis_master1_port}(?:@\d+)? .*$", "\1"); if (resp.http.Migration-NodeOrig !~ "[0-9a-f]+") { unset resp.http.Migration-NodeOrig; } } # Get the ID for the destination node (master2). master1.command("CLUSTER"); master1.push("NODES"); master1.execute(true); if (master1.reply_is_string()) { set resp.http.Migration-NodeDest = regsub(master1.get_reply(), "(?s)^(?:.+\n)?([0-9a-f]+) ${redis_master2_ip}:${redis_master2_port}(?:@\d+)? .*$", "\1"); if (resp.http.Migration-NodeDest !~ "[0-9a-f]+") { unset resp.http.Migration-NodeDest; } } # Mark the destination node as IMPORTING. master2.command("CLUSTER"); master2.push("SETSLOT"); master2.push(resp.http.Migration-Slot); master2.push("IMPORTING"); master2.push(resp.http.Migration-NodeOrig); master2.execute(true); if (master2.reply_is_status()) { set resp.http.Migration-Reply-4 = master2.get_status_reply(); } # Mark the original node as MIGRATING. master1.command("CLUSTER"); master1.push("SETSLOT"); master1.push(resp.http.Migration-Slot); master1.push("MIGRATING"); master1.push(resp.http.Migration-NodeDest); master1.execute(true); if (master1.reply_is_status()) { set resp.http.Migration-Reply-5 = master1.get_status_reply(); } # Migrate key. master1.command("MIGRATE"); master1.push("${redis_master2_ip}"); master1.push("${redis_master2_port}"); master1.push("${redis_key_in_master1}"); master1.push("0"); master1.push("0"); master1.execute(true); if (master1.reply_is_status()) { set resp.http.Migration-Reply-6 = master1.get_status_reply(); } # Assign the containing slot to the destination node in both nodes. master1.command("CLUSTER"); master1.push("SETSLOT"); master1.push(resp.http.Migration-Slot); master1.push("NODE"); master1.push(resp.http.Migration-NodeDest); master1.execute(true); if (master1.reply_is_status()) { set resp.http.Migration-Reply-7 = master1.get_status_reply(); } master2.command("CLUSTER"); master2.push("SETSLOT"); master2.push(resp.http.Migration-Slot); master2.push("NODE"); master2.push(resp.http.Migration-NodeDest); master2.execute(true); if (master2.reply_is_status()) { set resp.http.Migration-Reply-8 = master2.get_status_reply(); } # Check that the original node replies with a MOVED redirection. master1.command("GET"); master1.push("${redis_key_in_master1}"); master1.execute(true); if (master1.reply_is_error()) { if (master1.get_error_reply() ~ "^MOVED ") { set resp.http.Migration-Reply-9 = "MOVED"; } } } } -start client c1 { txreq rxresp expect resp.http.Reply-1 == "OK" expect resp.http.Migration-Slot != expect resp.http.Migration-NodeOrig != expect resp.http.Migration-NodeDest != expect resp.http.Migration-Reply-4 == "OK" expect resp.http.Migration-Reply-5 == "OK" expect resp.http.Migration-Reply-6 == "OK" expect resp.http.Migration-Reply-7 == "OK" expect resp.http.Migration-Reply-8 == "OK" expect resp.http.Migration-Reply-9 == "MOVED" expect resp.http.Reply-2 == "hello" expect resp.http.db-servers-total == "9" expect resp.http.db-connections-total == "2" expect resp.http.db-commands-total == "3" expect resp.http.db-cluster-discoveries-total == "2" expect resp.http.db-cluster-replies-moved == "1" expect resp.http.db-cluster-replies-ask == "0" } -run varnish v1 -expect client_req == 1 libvmod-redis-21.0/src/tests/clustered.basics-using-private-pool.vtc000066400000000000000000000153711476735432100256650ustar00rootroot00000000000000varnishtest "Tests basics using private pool" server s1 { rxreq txresp } -repeat 1 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=cluster, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=3, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=16); db.add_server("${redis_master2_ip}:${redis_master2_port}", cluster); db.add_server("${redis_master3_ip}:${redis_master3_port}", cluster); } sub vcl_deliver { # SET. db.command("SET"); db.push("${redis_key_in_master1}"); db.push("hello"); db.execute(true); if (db.reply_is_status()) { set resp.http.Reply-1 = db.get_status_reply(); } # SETEX. db.command("SETEX"); db.push("${redis_key_in_master2}"); db.push("3600"); db.push("Hello world!"); db.execute(true); if (db.reply_is_status()) { set resp.http.Reply-2 = db.get_status_reply(); } # GET. db.command("GET"); db.push("${redis_key_in_master2}"); db.execute(true); if (db.reply_is_string()) { set resp.http.Reply-3 = db.get_string_reply(); } # DEL. db.command("DEL"); db.push("${redis_key_in_master2}"); db.execute(true); if (db.reply_is_integer()) { set resp.http.Reply-4 = db.get_integer_reply(); } # MGET. db.command("MGET"); db.push("${redis_key_in_master1}"); db.push("{${redis_key_in_master1}}:other"); db.execute(true); if (db.reply_is_array()) { set resp.http.Reply-5-Length = db.get_array_reply_length(); set resp.http.Reply-5-Value-1 = db.get_array_reply_value(0); set resp.http.Reply-5-Value-2 = db.get_array_reply_value(1); } # MGET (CROSSSLOT). db.command("MGET"); db.push("${redis_key_in_master1}"); db.push("${redis_key_in_master2}"); db.execute(true); if (db.reply_is_error()) { set resp.http.Reply-6 = "1"; } # HMSET. db.command("HMSET"); db.push("${redis_key_in_master2}"); db.push("field1"); db.push("Hello world!"); db.push("field2"); db.push("42"); db.execute(true); if (db.reply_is_status()) { set resp.http.Reply-7 = db.get_status_reply(); } # HMGET. db.command("HGET"); db.push("${redis_key_in_master2}"); db.push("field1"); db.execute(true); if (db.reply_is_string()) { set resp.http.Reply-8 = db.get_string_reply(); } # INCR. db.command("INCR"); db.push("${redis_key_in_master1}"); db.execute(true); if (db.reply_is_error()) { set resp.http.Reply-9 = db.get_error_reply(); } # EVAL. set req.http.Script = {" redis.call('SET', KEYS[1], ARGV[1]) redis.call('SET', KEYS[2], ARGV[1]) "}; db.command("EVAL"); db.push(req.http.Script); db.push("2"); db.push("${redis_key_in_master1}"); db.push("{${redis_key_in_master1}}:other"); db.push("Atomic!"); db.execute(true); if (db.reply_is_nil()) { set resp.http.Reply-10 = "o/"; } # EVAL. db.command("EVAL"); db.push(req.http.Script); db.push("2"); db.push("${redis_key_in_master1}"); db.push("{${redis_key_in_master1}}:other"); db.push("Atomic x 2!"); db.execute(true); if (db.reply_is_nil()) { set resp.http.Reply-11 = "o/"; } # EVAL (CROSSSLOT). set req.http.Script = {" redis.call('SET', KEYS[1], ARGV[1]) redis.call('SET', KEYS[2], ARGV[1]) "}; db.command("EVAL"); db.push(req.http.Script); db.push("2"); db.push("${redis_key_in_master1}"); db.push("${redis_key_in_master2}"); db.push("Atomic!"); db.execute(true); if (db.reply_is_error()) { set resp.http.Reply-12 = "1"; } # GET. db.command("GET"); db.push("${redis_key_in_master1}"); db.execute(true); if (db.reply_is_string()) { set resp.http.Reply-13 = db.get_string_reply(); } # Stats. set resp.http.db-stats = db.stats(); set resp.http.db-servers-total = db.counter("servers.total"); set resp.http.db-connections-total = db.counter("connections.total"); set resp.http.db-commands-total = db.counter("commands.total"); set resp.http.db-commands-error = db.counter("commands.error"); set resp.http.db-commands-noscript = db.counter("commands.noscript"); set resp.http.db-cluster-discoveries-total = db.counter("cluster.discoveries.total"); set resp.http.db-cluster-replies-moved = db.counter("cluster.replies.moved"); set resp.http.db-cluster-replies-ask = db.counter("cluster.replies.ask"); } } -start # Needed for testing purposes, to store scripts in HTTP headers. varnish v1 -cliok "param.set feature -validate_headers" client c1 { txreq rxresp expect resp.http.Reply-1 == "OK" expect resp.http.Reply-2 == "OK" expect resp.http.Reply-3 == "Hello world!" expect resp.http.Reply-4 == "1" expect resp.http.Reply-5-Length == "2" expect resp.http.Reply-5-Value-1 == "hello" expect resp.http.Reply-5-Value-2 == "" expect resp.http.Reply-6 == "1" expect resp.http.Reply-7 == "OK" expect resp.http.Reply-8 == "Hello world!" expect resp.http.Reply-9 != "" expect resp.http.Reply-10 == "o/" expect resp.http.Reply-11 == "o/" expect resp.http.Reply-12 == "1" expect resp.http.Reply-13 == "Atomic x 2!" expect resp.http.db-servers-total == "9" expect resp.http.db-connections-total == "2" expect resp.http.db-commands-total == "13" expect resp.http.db-commands-error == "3" expect resp.http.db-commands-noscript == "1" expect resp.http.db-cluster-discoveries-total == "1" expect resp.http.db-cluster-replies-moved == "0" expect resp.http.db-cluster-replies-ask == "0" } -run varnish v1 -expect client_req == 1 libvmod-redis-21.0/src/tests/clustered.basics-using-shared-pool.vtc000066400000000000000000000153701476735432100254600ustar00rootroot00000000000000varnishtest "Tests basics using shared pool" server s1 { rxreq txresp } -repeat 1 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=cluster, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=true, max_connections=32, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=16); db.add_server("${redis_master2_ip}:${redis_master2_port}", cluster); db.add_server("${redis_master3_ip}:${redis_master3_port}", cluster); } sub vcl_deliver { # SET. db.command("SET"); db.push("${redis_key_in_master1}"); db.push("hello"); db.execute(true); if (db.reply_is_status()) { set resp.http.Reply-1 = db.get_status_reply(); } # SETEX. db.command("SETEX"); db.push("${redis_key_in_master2}"); db.push("3600"); db.push("Hello world!"); db.execute(true); if (db.reply_is_status()) { set resp.http.Reply-2 = db.get_status_reply(); } # GET. db.command("GET"); db.push("${redis_key_in_master2}"); db.execute(true); if (db.reply_is_string()) { set resp.http.Reply-3 = db.get_string_reply(); } # DEL. db.command("DEL"); db.push("${redis_key_in_master2}"); db.execute(true); if (db.reply_is_integer()) { set resp.http.Reply-4 = db.get_integer_reply(); } # MGET. db.command("MGET"); db.push("${redis_key_in_master1}"); db.push("{${redis_key_in_master1}}:other"); db.execute(true); if (db.reply_is_array()) { set resp.http.Reply-5-Length = db.get_array_reply_length(); set resp.http.Reply-5-Value-1 = db.get_array_reply_value(0); set resp.http.Reply-5-Value-2 = db.get_array_reply_value(1); } # MGET (CROSSSLOT). db.command("MGET"); db.push("${redis_key_in_master1}"); db.push("${redis_key_in_master2}"); db.execute(true); if (db.reply_is_error()) { set resp.http.Reply-6 = "1"; } # HMSET. db.command("HMSET"); db.push("${redis_key_in_master2}"); db.push("field1"); db.push("Hello world!"); db.push("field2"); db.push("42"); db.execute(true); if (db.reply_is_status()) { set resp.http.Reply-7 = db.get_status_reply(); } # HMGET. db.command("HGET"); db.push("${redis_key_in_master2}"); db.push("field1"); db.execute(true); if (db.reply_is_string()) { set resp.http.Reply-8 = db.get_string_reply(); } # INCR. db.command("INCR"); db.push("${redis_key_in_master1}"); db.execute(true); if (db.reply_is_error()) { set resp.http.Reply-9 = db.get_error_reply(); } # EVAL. set req.http.Script = {" redis.call('SET', KEYS[1], ARGV[1]) redis.call('SET', KEYS[2], ARGV[1]) "}; db.command("EVAL"); db.push(req.http.Script); db.push("2"); db.push("${redis_key_in_master1}"); db.push("{${redis_key_in_master1}}:other"); db.push("Atomic!"); db.execute(true); if (db.reply_is_nil()) { set resp.http.Reply-10 = "o/"; } # EVAL. db.command("EVAL"); db.push(req.http.Script); db.push("2"); db.push("${redis_key_in_master1}"); db.push("{${redis_key_in_master1}}:other"); db.push("Atomic x 2!"); db.execute(true); if (db.reply_is_nil()) { set resp.http.Reply-11 = "o/"; } # EVAL (CROSSSLOT). set req.http.Script = {" redis.call('SET', KEYS[1], ARGV[1]) redis.call('SET', KEYS[2], ARGV[1]) "}; db.command("EVAL"); db.push(req.http.Script); db.push("2"); db.push("${redis_key_in_master1}"); db.push("${redis_key_in_master2}"); db.push("Atomic!"); db.execute(true); if (db.reply_is_error()) { set resp.http.Reply-12 = "1"; } # GET. db.command("GET"); db.push("${redis_key_in_master1}"); db.execute(true); if (db.reply_is_string()) { set resp.http.Reply-13 = db.get_string_reply(); } # Stats. set resp.http.db-stats = db.stats(); set resp.http.db-servers-total = db.counter("servers.total"); set resp.http.db-connections-total = db.counter("connections.total"); set resp.http.db-commands-total = db.counter("commands.total"); set resp.http.db-commands-error = db.counter("commands.error"); set resp.http.db-commands-noscript = db.counter("commands.noscript"); set resp.http.db-cluster-discoveries-total = db.counter("cluster.discoveries.total"); set resp.http.db-cluster-replies-moved = db.counter("cluster.replies.moved"); set resp.http.db-cluster-replies-ask = db.counter("cluster.replies.ask"); } } -start # Needed for testing purposes, to store scripts in HTTP headers. varnish v1 -cliok "param.set feature -validate_headers" client c1 { txreq rxresp expect resp.http.Reply-1 == "OK" expect resp.http.Reply-2 == "OK" expect resp.http.Reply-3 == "Hello world!" expect resp.http.Reply-4 == "1" expect resp.http.Reply-5-Length == "2" expect resp.http.Reply-5-Value-1 == "hello" expect resp.http.Reply-5-Value-2 == "" expect resp.http.Reply-6 == "1" expect resp.http.Reply-7 == "OK" expect resp.http.Reply-8 == "Hello world!" expect resp.http.Reply-9 != "" expect resp.http.Reply-10 == "o/" expect resp.http.Reply-11 == "o/" expect resp.http.Reply-12 == "1" expect resp.http.Reply-13 == "Atomic x 2!" expect resp.http.db-servers-total == "9" expect resp.http.db-connections-total == "2" expect resp.http.db-commands-total == "13" expect resp.http.db-commands-error == "3" expect resp.http.db-commands-noscript == "1" expect resp.http.db-cluster-discoveries-total == "1" expect resp.http.db-cluster-replies-moved == "0" expect resp.http.db-cluster-replies-ask == "0" } -run varnish v1 -expect client_req == 1 libvmod-redis-21.0/src/tests/clustered.template.vtc000066400000000000000000000035631476735432100224720ustar00rootroot00000000000000varnishtest "Minimal test template" server s1 { rxreq txresp } -repeat 1 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=cluster, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=true, max_connections=32, password="", sickness_ttl=0, max_cluster_hops=16); db.add_server("${redis_master2_ip}:${redis_master2_port}", cluster); db.add_server("${redis_master3_ip}:${redis_master3_port}", cluster); } sub vcl_deliver { # Stats. set resp.http.db-stats = db.stats(); set resp.http.db-servers-total = db.counter("servers.total"); set resp.http.db-connections-total = db.counter("connections.total"); set resp.http.db-commands-total = db.counter("commands.total"); set resp.http.db-cluster-discoveries-total = db.counter("cluster.discoveries.total"); set resp.http.db-cluster-replies-moved = db.counter("cluster.replies.moved"); set resp.http.db-cluster-replies-ask = db.counter("cluster.replies.ask"); } } -start client c1 { txreq rxresp expect resp.http.db-servers-total == "9" expect resp.http.db-connections-total == "0" expect resp.http.db-commands-total == "0" expect resp.http.db-cluster-discoveries-total == "1" expect resp.http.db-cluster-replies-moved == "0" expect resp.http.db-cluster-replies-ask == "0" } -run varnish v1 -expect client_req == 1 libvmod-redis-21.0/src/tests/runner.sh000077500000000000000000000232651476735432100200210ustar00rootroot00000000000000#! /bin/bash ## ## Configuration. ## IPV6=0 DB_STANDALONE_MASTER_SERVERS=2 DB_STANDALONE_SLAVE_SERVERS=2 DB_STANDALONE_SENTINEL_SERVERS=3 DB_STANDALONE_START_PORT=40000 DB_CLUSTER_SERVERS=9 DB_CLUSTER_REPLICAS=2 DB_CLUSTER_START_PORT=50000 ## ## Cleanup callback. ## cleanup() { set +x for MASTER_INDEX in $(seq 1 $DB_STANDALONE_MASTER_SERVERS); do if [[ -s "$1/db-master$MASTER_INDEX.pid" ]]; then kill -9 $(cat "$1/db-master$MASTER_INDEX.pid") fi for SLAVE_INDEX in $(seq 1 $DB_STANDALONE_SLAVE_SERVERS); do if [[ -s "$1/db-slave${MASTER_INDEX}_$SLAVE_INDEX.pid" ]]; then kill -9 $(cat "$1/db-slave${MASTER_INDEX}_$SLAVE_INDEX.pid") fi done done for INDEX in $(seq 1 $DB_STANDALONE_SENTINEL_SERVERS); do if [[ -s "$1/db-sentinel$INDEX.pid" ]]; then kill -9 $(cat "$1/db-sentinel$INDEX.pid") fi done for INDEX in $(seq 1 $DB_CLUSTER_SERVERS); do if [[ -s "$1/db-server$INDEX.pid" ]]; then kill -9 $(cat "$1/db-server$INDEX.pid") fi done rm -rf "$1" echo } ## ## Initializations. ## set -e ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" TMP=`mktemp -d` chmod o+rwx "$TMP" CONTEXT="" ## ## Register cleanup callback. ## trap "cleanup $TMP" EXIT ## ## Check CLI is available & get DB version. Fail test if DB is not available. ## if [ -x "$(command -v redis-cli)" ]; then VERSION=$(redis-cli --version | sed "s/^redis-cli \([^ ]*\).*$/\1/" | awk -F. '{ printf("%d%03d%03d\n", $1, $2, $3) }') CONTEXT="\ $CONTEXT \ -Dredis_version=$VERSION \ -Dredis_tls_cafile=$ROOT/assets/tls-ca-certificate.crt \ -Dredis_tls_certfile=$ROOT/assets/tls-certificate.crt \ -Dredis_tls_keyfile=$ROOT/assets/tls-certificate.key" else echo 'Database not found!' exit 1 fi ## ## Silently pass test if minimum DB version is not fulfilled. ## if [[ ${@: -1} =~ ^.*\.([0-9]{7,})\.[^\.]*\.vtc(\.disabled)?$ ]]; then if [ "$VERSION" -lt "${BASH_REMATCH[1]}" ]; then echo 'Test silently skipped! A newer DB version is needed.' exit 0 fi fi ## ## Launch standalone DB servers? ## if [[ ${@: -1} =~ ^.*standalone(\.[0-9]{7,})?\.[^\.]*\.vtc(\.disabled)?$ ]]; then for MASTER_INDEX in $(seq 1 $DB_STANDALONE_MASTER_SERVERS); do [[ $IPV6 = 1 ]] && MASTER_IP=::1 || MASTER_IP=127.0.0.$MASTER_INDEX MASTER_PORT=$((DB_STANDALONE_START_PORT+MASTER_INDEX)) MASTER_TLS_PORT=$((MASTER_PORT+1000)) cat > "$TMP/db-master$MASTER_INDEX.conf" <> "$TMP/db-master$MASTER_INDEX.conf" <> "$TMP/db-master$MASTER_INDEX.conf" < "$TMP/db-slave${MASTER_INDEX}_$SLAVE_INDEX.conf" <> "$TMP/db-slave${MASTER_INDEX}_$SLAVE_INDEX.conf" <> "$TMP/db-sentinel$SENTINEL_INDEX.conf" <> "$TMP/db-sentinel$INDEX.conf" <> "$TMP/db-sentinel$INDEX.conf" < "$TMP/db-server$INDEX.conf" <> "$TMP/db-server$INDEX.conf" < /dev/null else yes yes | redis-trib.rb create --replicas $DB_CLUSTER_REPLICAS $SERVERS > /dev/null fi # Wait for cluster formation in a rudementary way. [[ $IPV6 = 1 ]] && HOST=::1 || HOST=127.0.0.1 [[ $IPV6 = 1 ]] && PATTERN=::1 || PATTERN=127[.]0[.]0[.] while [ $(redis-cli -h $HOST -p $((DB_CLUSTER_START_PORT+1)) CLUSTER SLOTS | grep "$PATTERN" | wc -l) -lt $DB_CLUSTER_SERVERS ]; do sleep 1 done sleep 1 # Add to context: # - All master nodes' addresses ordered by the slots they handle # (redis_master1, redis_master2, ...). # - An example key for each of those master nodes (redis_key_in_master1, # redis_key_in_master2, ...). INDEX=1 while read LINE; do CONTEXT="\ $CONTEXT \ -Dredis_master${INDEX}_ip=$(echo $LINE | cut -f 2 -d ' ' | cut -f 1 -d '@' | rev | cut -f 2- -d ':' | rev) \ -Dredis_master${INDEX}_port=$(echo $LINE | cut -f 2 -d ' ' | cut -f 1 -d '@' | rev | cut -f 1 -d ':' | rev) \ -Dredis_key_in_master${INDEX}=$(grep "^$(echo $LINE | cut -f 9 -d ' ' | cut -f 1 -d '-'): " $ROOT/assets/hashslot-keys.txt | cut -f 2 -d ' ')" INDEX=$(( INDEX + 1 )) done <<< "$(redis-cli -h $HOST -p $((DB_CLUSTER_START_PORT+1)) CLUSTER NODES | grep master | sort -k 9 -n)" fi ## ## Execute wrapped command? ## set -x "$1" $CONTEXT "${@:2}" libvmod-redis-21.0/src/tests/standalone.6000000.TLS.vtc000066400000000000000000000047771476735432100222730ustar00rootroot00000000000000varnishtest "Tests TLS support" server s1 { rxreq txresp } -repeat 1 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db = redis.db( location="${redis_master1_ip}:${redis_master1_tls_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=1, tls=true, tls_cafile="${redis_tls_cafile}", tls_certfile="${redis_tls_certfile}", tls_keyfile="${redis_tls_keyfile}", password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); } sub vcl_deliver { # SET. db.command("SET"); db.push("foo"); db.push("Hello world!"); db.execute(true); if (db.reply_is_status()) { set resp.http.Reply-1 = db.get_status_reply(); } # GET. db.command("GET"); db.push("foo"); db.execute(true); if (db.reply_is_string()) { set resp.http.Reply-2 = db.get_string_reply(); } # Stats. set resp.http.db-stats = db.stats(); set resp.http.db-servers-total = db.counter("servers.total"); set resp.http.db-connections-total = db.counter("connections.total"); set resp.http.db-connections-dropped-error = db.counter("connections.dropped.error"); set resp.http.db-commands-total = db.counter("commands.total"); set resp.http.db-commands-error = db.counter("commands.error"); set resp.http.db-commands-failed = db.counter("commands.failed"); set resp.http.db-commands-noscript = db.counter("commands.noscript"); } } -start client c1 { txreq rxresp expect resp.http.Reply-1 == "OK" expect resp.http.Reply-2 == "Hello world!" expect resp.http.db-servers-total == "1" expect resp.http.db-connections-total == "1" expect resp.http.db-connections-dropped-error == "0" expect resp.http.db-commands-total == "2" expect resp.http.db-commands-failed == "0" expect resp.http.db-commands-error == "0" expect resp.http.db-commands-noscript == "0" } -run varnish v1 -expect client_req == 1 libvmod-redis-21.0/src/tests/standalone.6000000.sentinels.vtc.disabled000066400000000000000000000111121476735432100253600ustar00rootroot00000000000000varnishtest "Tests Sentinels + TLS + RESP3." server s1 { rxreq txresp } -repeat 3 -start # Let Sentinels discover all master and slave servers. delay 15 # Varnish configured with no password to connect to sentinels. varnish v1 -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={" ${redis_sentinel1_ip}:${redis_sentinel1_tls_port}, ${redis_sentinel2_ip}:${redis_sentinel2_tls_port}, ${redis_sentinel3_ip}:${redis_sentinel3_tls_port} "}, period=3, connection_timeout=500, command_timeout=0, protocol=RESP3, tls=true, tls_cafile="${redis_tls_cafile}", tls_certfile="${redis_tls_certfile}", tls_keyfile="${redis_tls_keyfile}"); } } -start # Varnish configured with an incorrect password to connect to sentinels. varnish v2 -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={" ${redis_sentinel1_ip}:${redis_sentinel1_tls_port}, ${redis_sentinel2_ip}:${redis_sentinel2_tls_port}, ${redis_sentinel3_ip}:${redis_sentinel3_tls_port} "}, period=3, connection_timeout=500, command_timeout=0, protocol=RESP3, tls=true, tls_cafile="${redis_tls_cafile}", tls_certfile="${redis_tls_certfile}", tls_keyfile="${redis_tls_keyfile}", password="wrong-password"); } } -start # Varnish configured with a correct password to connect to sentinels. varnish v3 -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={" ${redis_sentinel1_ip}:${redis_sentinel1_tls_port}, ${redis_sentinel2_ip}:${redis_sentinel2_tls_port}, ${redis_sentinel3_ip}:${redis_sentinel3_tls_port} "}, period=3, connection_timeout=500, command_timeout=0, protocol=RESP3, tls=true, tls_cafile="${redis_tls_cafile}", tls_certfile="${redis_tls_certfile}", tls_keyfile="${redis_tls_keyfile}", password="s3cr3t"); new db = redis.db( location="${redis_master1_ip}:${redis_master1_tls_port}", type=auto, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=2, protocol=RESP3, tls=true, tls_cafile="${redis_tls_cafile}", tls_certfile="${redis_tls_certfile}", tls_keyfile="${redis_tls_keyfile}", password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); db.add_server("${redis_slave1_1_ip}:${redis_slave1_1_tls_port}", auto); db.add_server("${redis_slave1_2_ip}:${redis_slave1_2_tls_port}", auto); } sub vcl_deliver { # Simulate unreachable master. db.command("DEBUG"); db.push("sleep"); db.push("20"); db.execute(true); # Stats. set resp.http.db-stats = db.stats(); } } -start delay 1 logexpect l1 -v v1 -g raw client c1 -connect ${v1_sock} { txreq rxresp } -run logexpect l1 { expect * 0 VCL_Error {^\[REDIS\]\[helloCallback:.*Failed to negotiate protocol in Sentinel connection.*NOAUTH.*} expect * 0 VCL_Error {^\[REDIS\]\[disconnectCallback:.*Sentinel connection lost.*NOAUTH.*} expect * 0 VCL_Error {^\[REDIS\]\[discover_servers:.*Failed to execute Sentinel HELLO command.*NOAUTH.*} } -start logexpect l1 -wait logexpect l2 -v v2 -g raw client c2 -connect ${v2_sock} { txreq rxresp } -run logexpect l2 { expect * 0 VCL_Error {^\[REDIS\]\[authorizeCallback:.*Failed to authenticate Sentinel connection.*WRONGPASS.*} expect * 0 VCL_Error {^\[REDIS\]\[disconnectCallback:.*Sentinel connection lost.*NOAUTH.*} expect * 0 VCL_Error {^\[REDIS\]\[discover_servers:.*Failed to execute Sentinel AUTH command.*WRONGPASS.*} } -start logexpect l2 -wait client c3 -connect ${v3_sock} { txreq rxresp } -run delay 5 # XXX: not really an useful test at the moment. varnish v1 -expect client_req == 1 varnish v2 -expect client_req == 1 varnish v3 -expect client_req == 1 libvmod-redis-21.0/src/tests/standalone.VCL-temperature-and-discard.vtc000066400000000000000000000027551476735432100261450ustar00rootroot00000000000000varnishtest "Test VCL temperature and discard." server s1 { rxreq txresp } -repeat 1 -start varnish v1 -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db1 = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); new db2 = redis.db( location="${redis_master2_ip}:${redis_master2_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=true, max_connections=32, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); } } -start varnish v1 -vcl+backend { } varnish v1 -cliok "vcl.state vcl1 cold" varnish v1 -cliok "vcl.state vcl1 warm" varnish v1 -cliok "vcl.use vcl1" varnish v1 -cliok "vcl.use vcl2" varnish v1 -cliok "vcl.discard vcl1" varnish v1 -expect MGT.child_panic == 0 libvmod-redis-21.0/src/tests/standalone.auto-role.vtc000066400000000000000000000040451476735432100227200ustar00rootroot00000000000000varnishtest "Test 'auto' role" server s1 { rxreq txresp } -repeat 1 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=auto, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=2, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); db.add_server("${redis_slave1_1_ip}:${redis_slave1_1_port}", auto); } sub vcl_deliver { # Fetch role (master). db.command("ROLE"); db.execute(true); if (db.reply_is_array() && db.get_array_reply_length() > 0 && db.array_reply_is_string(0)) { set resp.http.Reply-1 = db.get_array_reply_value(0); } # Fetch role (slave). db.command("ROLE"); db.execute(false); if (db.reply_is_array() && db.get_array_reply_length() > 0 && db.array_reply_is_string(0)) { set resp.http.Reply-2 = db.get_array_reply_value(0); } # Stats. set resp.http.db-stats = db.stats(); set resp.http.db-servers-total = db.counter("servers.total"); set resp.http.db-connections-total = db.counter("connections.total"); set resp.http.db-commands-total = db.counter("commands.total"); } } -start client c1 { txreq rxresp expect resp.http.Reply-1 == "master" expect resp.http.Reply-2 == "slave" expect resp.http.db-servers-total == "2" expect resp.http.db-connections-total == "2" expect resp.http.db-commands-total == "2" } -run varnish v1 -expect client_req == 1 libvmod-redis-21.0/src/tests/standalone.basics-using-private-pool.vtc000066400000000000000000000130441476735432100260160ustar00rootroot00000000000000varnishtest "Tests basics using private pool" server s1 { rxreq txresp } -repeat 1 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); } sub vcl_deliver { # SET. db.command("SET"); db.push("foo"); db.push("hello"); db.execute(true); if (db.reply_is_status()) { set resp.http.Reply-1 = db.get_status_reply(); } # SETEX. db.command("SETEX"); db.push("bar"); db.push("3600"); db.push("Hello world!"); db.execute(true); if (db.reply_is_status()) { set resp.http.Reply-2 = db.get_status_reply(); } # GET. db.command("GET"); db.push("bar"); db.execute(true); if (db.reply_is_string()) { set resp.http.Reply-3 = db.get_string_reply(); } # DEL. db.command("DEL"); db.push("bar"); db.execute(true); if (db.reply_is_integer()) { set resp.http.Reply-4 = db.get_integer_reply(); } # MGET. db.command("MGET"); db.push("foo"); db.push("bar"); db.execute(true); if (db.reply_is_array()) { set resp.http.Reply-5-Length = db.get_array_reply_length(); set resp.http.Reply-5-Value-1 = db.get_array_reply_value(0); set resp.http.Reply-5-Value-2 = db.get_array_reply_value(1); } # HMSET. db.command("HMSET"); db.push("bar"); db.push("field1"); db.push("Hello world!"); db.push("field2"); db.push("42"); db.execute(true); if (db.reply_is_status()) { set resp.http.Reply-6 = db.get_status_reply(); } # HMGET. db.command("HGET"); db.push("bar"); db.push("field1"); db.execute(true); if (db.reply_is_string()) { set resp.http.Reply-7 = db.get_string_reply(); } # INCR. db.command("INCR"); db.push("foo"); db.execute(true); if (db.reply_is_error()) { set resp.http.Reply-8 = db.get_error_reply(); } # EVAL. set req.http.Script = {" redis.call('SET', KEYS[1], ARGV[1]) redis.call('SET', KEYS[2], ARGV[1]) "}; db.command("EVAL"); db.push(req.http.Script); db.push("2"); db.push("foo"); db.push("bar"); db.push("Atomic!"); db.execute(true); if (db.reply_is_nil()) { set resp.http.Reply-9 = "o/"; } # EVAL. db.command("EVAL"); db.push(req.http.Script); db.push("2"); db.push("foo"); db.push("bar"); db.push("Atomic x 2!"); db.execute(true); if (db.reply_is_nil()) { set resp.http.Reply-10 = "o/"; } # GET. db.command("GET"); db.push("foo"); db.execute(true); if (db.reply_is_string()) { set resp.http.Reply-11 = db.get_string_reply(); } # EVAL (large integer). set req.http.Script = {" return tonumber(ARGV[1]) "}; db.command("EVAL"); db.push(req.http.Script); db.push("0"); db.push("34359738368"); # 2^39 -- See VRT_INTEGER_MAX & VRT_DECIMAL_MAX. db.execute(true); if (db.reply_is_integer()) { set resp.http.Reply-12 = db.get_integer_reply(); } # Stats. set resp.http.db-stats = db.stats(); set resp.http.db-servers-total = db.counter("servers.total"); set resp.http.db-connections-total = db.counter("connections.total"); set resp.http.db-commands-total = db.counter("commands.total"); set resp.http.db-commands-error = db.counter("commands.error"); set resp.http.db-commands-noscript = db.counter("commands.noscript"); } } -start # Needed for testing purposes, to store scripts in HTTP headers. varnish v1 -cliok "param.set feature -validate_headers" client c1 { txreq rxresp expect resp.http.Reply-1 == "OK" expect resp.http.Reply-2 == "OK" expect resp.http.Reply-3 == "Hello world!" expect resp.http.Reply-4 == "1" expect resp.http.Reply-5-Length == "2" expect resp.http.Reply-5-Value-1 == "hello" expect resp.http.Reply-5-Value-2 == "" expect resp.http.Reply-6 == "OK" expect resp.http.Reply-7 == "Hello world!" expect resp.http.Reply-8 != "" expect resp.http.Reply-9 == "o/" expect resp.http.Reply-10 == "o/" expect resp.http.Reply-11 == "Atomic x 2!" expect resp.http.Reply-12 == "34359738368" expect resp.http.db-servers-total == "1" expect resp.http.db-connections-total == "1" expect resp.http.db-commands-total == "12" expect resp.http.db-commands-error == "1" expect resp.http.db-commands-noscript == "2" } -run varnish v1 -expect client_req == 1 libvmod-redis-21.0/src/tests/standalone.basics-with-multiple-servers-and-private-pool.vtc000066400000000000000000000104431476735432100317240ustar00rootroot00000000000000varnishtest "Tests basics with multiple servers and private pool" server s1 { rxreq txresp } -repeat 1 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new master1 = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); new master2 = redis.db( location="${redis_master2_ip}:${redis_master2_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); } sub vcl_deliver { # SET (master1) -> GET (master1) -> GET (master2). master1.command("SET"); master1.push("foo"); master1.push("Hello world!"); master1.execute(true); master1.command("GET"); master1.push("foo"); master1.execute(true); set resp.http.Reply-1 = master1.get_reply(); master2.command("GET"); master2.push("foo"); master2.execute(true); set resp.http.Reply-2 = master2.get_reply(); # SET (master2) -> GET (master2) -> GET (master1). master2.command("SET"); master2.push("bar"); master2.push("Hello world!"); master2.execute(true); master2.command("GET"); master2.push("bar"); master2.execute(true); set resp.http.Reply-3 = master2.get_reply(); master1.command("GET"); master1.push("bar"); master1.execute(true); set resp.http.Reply-4 = master1.get_reply(); # Stats. set resp.http.master1-stats = master1.stats(); set resp.http.master1-servers-total = master1.counter("servers.total"); set resp.http.master1-connections-total = master1.counter("connections.total"); set resp.http.master1-connections-dropped-overflow = master1.counter("connections.dropped.overflow"); set resp.http.master1-commands-total = master1.counter("commands.total"); set resp.http.master1-commands-error = master1.counter("commands.error"); set resp.http.master1-commands-noscript = master1.counter("commands.noscript"); set resp.http.master2-stats = master2.stats(); set resp.http.master2-servers-total = master2.counter("servers.total"); set resp.http.master2-connections-dropped-overflow = master2.counter("connections.dropped.overflow"); set resp.http.master2-connections-total = master2.counter("connections.total"); set resp.http.master2-commands-total = master2.counter("commands.total"); set resp.http.master2-commands-error = master2.counter("commands.error"); set resp.http.master2-commands-noscript = master2.counter("commands.noscript"); } } -start client c1 { txreq rxresp expect resp.http.Reply-1 == "Hello world!" expect resp.http.Reply-2 == "" expect resp.http.Reply-3 == "Hello world!" expect resp.http.Reply-4 == "" expect resp.http.master1-servers-total == "1" expect resp.http.master1-connections-total == "2" expect resp.http.master1-connections-dropped-overflow == "1" expect resp.http.master1-commands-total == "3" expect resp.http.master1-commands-error == "0" expect resp.http.master1-commands-noscript == "0" expect resp.http.master2-servers-total == "1" expect resp.http.master2-connections-total == "1" expect resp.http.master2-connections-dropped-overflow == "1" expect resp.http.master2-commands-total == "3" expect resp.http.master2-commands-error == "0" expect resp.http.master2-commands-noscript == "0" } -run varnish v1 -expect client_req == 1 libvmod-redis-21.0/src/tests/standalone.basics-with-multiple-servers-and-shared-pool.vtc000066400000000000000000000104401476735432100315150ustar00rootroot00000000000000varnishtest "Tests basics with multiple servers and shared pool" server s1 { rxreq txresp } -repeat 1 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new master1 = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=true, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); new master2 = redis.db( location="${redis_master2_ip}:${redis_master2_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=true, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); } sub vcl_deliver { # SET (master1) -> GET (master1) -> GET (master2). master1.command("SET"); master1.push("foo"); master1.push("Hello world!"); master1.execute(true); master1.command("GET"); master1.push("foo"); master1.execute(true); set resp.http.Reply-1 = master1.get_reply(); master2.command("GET"); master2.push("foo"); master2.execute(true); set resp.http.Reply-2 = master2.get_reply(); # SET (master2) -> GET (master2) -> GET (master1). master2.command("SET"); master2.push("bar"); master2.push("Hello world!"); master2.execute(true); master2.command("GET"); master2.push("bar"); master2.execute(true); set resp.http.Reply-3 = master2.get_reply(); master1.command("GET"); master1.push("bar"); master1.execute(true); set resp.http.Reply-4 = master1.get_reply(); # Stats. set resp.http.master1-stats = master1.stats(); set resp.http.master1-servers-total = master1.counter("servers.total"); set resp.http.master1-connections-total = master1.counter("connections.total"); set resp.http.master1-connections-dropped-overflow = master1.counter("connections.dropped.overflow"); set resp.http.master1-commands-total = master1.counter("commands.total"); set resp.http.master1-commands-error = master1.counter("commands.error"); set resp.http.master1-commands-noscript = master1.counter("commands.noscript"); set resp.http.master2-stats = master2.stats(); set resp.http.master2-servers-total = master2.counter("servers.total"); set resp.http.master2-connections-dropped-overflow = master2.counter("connections.dropped.overflow"); set resp.http.master2-connections-total = master2.counter("connections.total"); set resp.http.master2-commands-total = master2.counter("commands.total"); set resp.http.master2-commands-error = master2.counter("commands.error"); set resp.http.master2-commands-noscript = master2.counter("commands.noscript"); } } -start client c1 { txreq rxresp expect resp.http.Reply-1 == "Hello world!" expect resp.http.Reply-2 == "" expect resp.http.Reply-3 == "Hello world!" expect resp.http.Reply-4 == "" expect resp.http.master1-servers-total == "1" expect resp.http.master1-connections-total == "1" expect resp.http.master1-connections-dropped-overflow == "0" expect resp.http.master1-commands-total == "3" expect resp.http.master1-commands-error == "0" expect resp.http.master1-commands-noscript == "0" expect resp.http.master2-servers-total == "1" expect resp.http.master2-connections-total == "1" expect resp.http.master2-connections-dropped-overflow == "0" expect resp.http.master2-commands-total == "3" expect resp.http.master2-commands-error == "0" expect resp.http.master2-commands-noscript == "0" } -run varnish v1 -expect client_req == 1 libvmod-redis-21.0/src/tests/standalone.blocked-workers.vtc000066400000000000000000000041361476735432100241070ustar00rootroot00000000000000varnishtest "Tests workers are blocked when using a small shared pool" server s1 { rxreq txresp } -repeat 2 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=true, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); } sub vcl_deliver { # Slow vs fast command. if (req.http.Slow == "1") { db.command("DEBUG"); db.push("sleep"); db.push("3"); } else { db.command("SET"); db.push("foo"); db.push("hello"); } db.execute(true); set resp.http.Replied = db.replied(); set resp.http.Reply = db.get_reply(); # Stats. set resp.http.db-stats = db.stats(); set resp.http.db-servers-total = db.counter("servers.total"); set resp.http.db-connections-total = db.counter("connections.total"); set resp.http.db-workers-blocked = db.counter("workers.blocked"); set resp.http.db-commands-total = db.counter("commands.total"); } } -start client c1 { txreq -hdr "Slow: 1" rxresp expect resp.http.Replied == "true" expect resp.http.Reply == "OK" } -start delay 1.0 client c2 { txreq -hdr "Slow: 0" rxresp expect resp.http.Replied == "true" expect resp.http.Reply == "OK" expect resp.http.db-servers-total == "1" expect resp.http.db-connections-total == "1" expect resp.http.db-workers-blocked == "1" expect resp.http.db-commands-total == "2" } -run varnish v1 -expect client_req == 2 libvmod-redis-21.0/src/tests/standalone.command-execution-timeout.vtc000066400000000000000000000074051476735432100261170ustar00rootroot00000000000000varnishtest "Tests command execution timeout" server s1 { rxreq txresp } -repeat 1 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); } sub vcl_deliver { # Fast command (no timeout). db.command("SET"); db.push("foo"); db.push("hello"); db.execute(true); set resp.http.Replied-1 = db.replied(); set resp.http.Reply-1 = db.get_reply(); # Slow command (no timeout). db.command("DEBUG"); db.push("sleep"); db.push("3"); db.execute(true); set resp.http.Replied-2 = db.replied(); set resp.http.Reply-2 = db.get_reply(); # Fast command (1000 ms timeout). db.command("SET"); db.push("foo"); db.push("hello"); db.timeout(1000); db.execute(true); set resp.http.Replied-3 = db.replied(); set resp.http.Reply-3 = db.get_reply(); # Slow command (1000 ms timeout). db.command("DEBUG"); db.push("sleep"); db.push("3"); db.timeout(1000); db.execute(true); set resp.http.Replied-4 = db.replied(); set resp.http.Reply-4 = db.get_reply(); # Fast command (no timeout). db.command("SET"); db.push("foo"); db.push("hello"); db.execute(true); set resp.http.Replied-5 = db.replied(); set resp.http.Reply-5 = db.get_reply(); # Slow command (no timeout). db.command("DEBUG"); db.push("sleep"); db.push("3"); db.execute(true); set resp.http.Replied-6 = db.replied(); set resp.http.Reply-6 = db.get_reply(); # Stats. set resp.http.db-stats = db.stats(); set resp.http.db-servers-total = db.counter("servers.total"); set resp.http.db-connections-total = db.counter("connections.total"); set resp.http.db-connections-dropped-error = db.counter("connections.dropped.error"); set resp.http.db-commands-total = db.counter("commands.total"); set resp.http.db-commands-error = db.counter("commands.error"); set resp.http.db-commands-failed = db.counter("commands.failed"); set resp.http.db-commands-noscript = db.counter("commands.noscript"); } } -start client c1 { txreq rxresp expect resp.http.Replied-1 == "true" expect resp.http.Reply-1 == "OK" expect resp.http.Replied-2 == "true" expect resp.http.Reply-2 == "OK" expect resp.http.Replied-3 == "true" expect resp.http.Reply-3 == "OK" expect resp.http.Replied-4 == "false" expect resp.http.Reply-4 == "" expect resp.http.Replied-5 == "true" expect resp.http.Reply-5 == "OK" expect resp.http.Replied-6 == "true" expect resp.http.Reply-6 == "OK" expect resp.http.db-servers-total == "1" expect resp.http.db-connections-total == "2" expect resp.http.db-connections-dropped-error == "1" expect resp.http.db-commands-total == "5" expect resp.http.db-commands-failed == "1" expect resp.http.db-commands-error == "0" expect resp.http.db-commands-noscript == "0" } -run varnish v1 -expect client_req == 1 libvmod-redis-21.0/src/tests/standalone.easy-command-timeout.vtc000066400000000000000000000067761476735432100250670ustar00rootroot00000000000000varnishtest "Tests easy_execution timeout" server s1 { rxreq txresp } -repeat 1 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); } sub vcl_deliver { # Fast command (no timeout). db.easy_execute("SET", "foo", "hello", master = true); set resp.http.Replied-1 = db.replied(); set resp.http.Reply-1 = db.get_reply(); # Slow command (no timeout). db.easy_execute("DEBUG", "sleep", "3", master = true); set resp.http.Replied-2 = db.replied(); set resp.http.Reply-2 = db.get_reply(); # Fast command (1000 ms timeout). db.easy_execute("SET", "foo", "hello", master = true, timeout = 1000); set resp.http.Replied-3 = db.replied(); set resp.http.Reply-3 = db.get_reply(); # Slow command (1000 ms timeout). db.easy_execute("DEBUG", "sleep", "3", master = true, timeout = 1000); set resp.http.Replied-4 = db.replied(); set resp.http.Reply-4 = db.get_reply(); # Fast command (no timeout). db.easy_execute("SET", "foo", "hello", master = true); set resp.http.Replied-5 = db.replied(); set resp.http.Reply-5 = db.get_reply(); # Slow command (no timeout). db.easy_execute("DEBUG", "sleep", "3", master = true); set resp.http.Replied-6 = db.replied(); set resp.http.Reply-6 = db.get_reply(); # Stats. set resp.http.db-stats = db.stats(); set resp.http.db-servers-total = db.counter("servers.total"); set resp.http.db-connections-total = db.counter("connections.total"); set resp.http.db-connections-dropped-error = db.counter("connections.dropped.error"); set resp.http.db-commands-total = db.counter("commands.total"); set resp.http.db-commands-error = db.counter("commands.error"); set resp.http.db-commands-failed = db.counter("commands.failed"); set resp.http.db-commands-noscript = db.counter("commands.noscript"); } } -start client c1 { txreq rxresp expect resp.http.Replied-1 == "true" expect resp.http.Reply-1 == "OK" expect resp.http.Replied-2 == "true" expect resp.http.Reply-2 == "OK" expect resp.http.Replied-3 == "true" expect resp.http.Reply-3 == "OK" expect resp.http.Replied-4 == "false" expect resp.http.Reply-4 == "" expect resp.http.Replied-5 == "true" expect resp.http.Reply-5 == "OK" expect resp.http.Replied-6 == "true" expect resp.http.Reply-6 == "OK" expect resp.http.db-servers-total == "1" expect resp.http.db-connections-total == "2" expect resp.http.db-connections-dropped-error == "1" expect resp.http.db-commands-total == "5" expect resp.http.db-commands-failed == "1" expect resp.http.db-commands-error == "0" expect resp.http.db-commands-noscript == "0" } -run varnish v1 -expect client_req == 1 libvmod-redis-21.0/src/tests/standalone.password-protected-instances.vtc000066400000000000000000000175761476735432100266440ustar00rootroot00000000000000varnishtest "Tests password protected instances" server s1 { rxreq txresp } -repeat 3 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); } sub vcl_deliver { # SET. db.command("SET"); db.push("foo"); db.push("hello"); db.execute(true); if (db.reply_is_status()) { set resp.http.Reply-1 = db.get_status_reply(); } # CONFIG SET. db.command("CONFIG"); db.push("SET"); db.push("requirepass"); db.push("s3cr3t"); db.execute(true); if (db.reply_is_status()) { set resp.http.Reply-2 = db.get_status_reply(); } } } -start varnish v2 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db1 = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=3, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); new db2 = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=3, password="42", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); new db3 = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=3, password="s3cr3t", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); } sub vcl_deliver { # GET (no password). db1.command("GET"); db1.push("foo"); db1.execute(true); if (db1.reply_is_error() && (db1.get_error_reply() ~ "NOAUTH")) { set resp.http.Reply-1 = "o/"; } # GET (wrong password). db2.command("GET"); db2.push("foo"); db2.execute(true); if (!db2.replied()) { set resp.http.Reply-2 = "o/"; } # GET (right password). db3.command("GET"); db3.push("foo"); db3.execute(true); if (db3.reply_is_string()) { set resp.http.Reply-3 = db3.get_string_reply(); } # ACL. if (${redis_version} >= 6000000) { db3.command("ACL"); db3.push("SETUSER"); db3.push("alice"); db3.push("on"); db3.push(">t0ps3cr3t"); db3.push("~foo*"); db3.push("+get"); db3.execute(true); if (db3.reply_is_status()) { set resp.http.Reply-4 = db3.get_status_reply(); } } else { set resp.http.Reply-4 = "OK"; } } } -start varnish v3 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db1 = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=3, user="alice", password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); new db2 = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=3, user="alice", password="s3cr3t", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); new db3 = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=3, user="alice", password="t0ps3cr3t", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); } sub vcl_deliver { # GET (no password). if (${redis_version} >= 6000000) { db1.command("GET"); db1.push("foo"); db1.execute(true); if (db1.reply_is_error() && (db1.get_error_reply() ~ "NOAUTH")) { set resp.http.Reply-1 = "o/"; } } else { set resp.http.Reply-1 = "o/"; } # GET (wrong password). if (${redis_version} >= 6000000) { db2.command("GET"); db2.push("foo"); db2.execute(true); if (!db2.replied()) { set resp.http.Reply-2 = "o/"; } } else { set resp.http.Reply-2 = "o/"; } # GET (right password). if (${redis_version} >= 6000000) { db3.command("GET"); db3.push("foo"); db3.execute(true); if (db3.reply_is_string()) { set resp.http.Reply-3 = db3.get_string_reply(); } } else { set resp.http.Reply-3 = "hello"; } # GET (right password but no permissions). if (${redis_version} >= 6000000) { db3.command("GET"); db3.push("bar"); db3.execute(true); if (db3.reply_is_error() && (db3.get_error_reply() ~ "NOPERM")) { set resp.http.Reply-4 = "o/"; } } else { set resp.http.Reply-4 = "o/"; } } } -start client c1 { txreq rxresp expect resp.http.Reply-1 == "OK" expect resp.http.Reply-2 == "OK" } -run client c2 -connect ${v2_sock} { txreq rxresp expect resp.http.Reply-1 == "o/" expect resp.http.Reply-2 == "o/" expect resp.http.Reply-3 == "hello" expect resp.http.Reply-4 == "OK" } -run client c3 -connect ${v3_sock} { txreq rxresp expect resp.http.Reply-1 == "o/" expect resp.http.Reply-2 == "o/" expect resp.http.Reply-3 == "hello" expect resp.http.Reply-4 == "o/" } -run varnish v1 -expect client_req == 1 varnish v2 -expect client_req == 1 varnish v3 -expect client_req == 1 libvmod-redis-21.0/src/tests/standalone.prometheus-stats.vtc000066400000000000000000000117601476735432100243420ustar00rootroot00000000000000varnishtest "Test Prometheus stats" server s1 { } -repeat 1 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); } sub vcl_recv { return (synth(200, "OK")); } sub vcl_synth { if (req.http.stream) { db.stats( format=prometheus, stream=true, prometheus_name_prefix=req.http.prefix, prometheus_default_labels=(req.http.default-labels == "1"), prometheus_extra_labels=req.http.extra-labels); } else { synthetic(db.stats( format=prometheus, stream=false, prometheus_name_prefix=req.http.prefix, prometheus_default_labels=(req.http.default-labels == "1"), prometheus_extra_labels=req.http.extra-labels)); } return (deliver); } } -start client c1 { txreq rxresp expect resp.body == {# TYPE vmod_redis_servers_total counter vmod_redis_servers_total{} 1 # TYPE vmod_redis_servers_failed counter vmod_redis_servers_failed{} 0 # TYPE vmod_redis_connections_total counter vmod_redis_connections_total{} 0 # TYPE vmod_redis_connections_failed counter vmod_redis_connections_failed{} 0 # TYPE vmod_redis_connections_dropped counter vmod_redis_connections_dropped{reason="error"} 0 vmod_redis_connections_dropped{reason="hung_up"} 0 vmod_redis_connections_dropped{reason="overflow"} 0 vmod_redis_connections_dropped{reason="ttl"} 0 vmod_redis_connections_dropped{reason="version"} 0 vmod_redis_connections_dropped{reason="sick"} 0 # TYPE vmod_redis_workers_blocked counter vmod_redis_workers_blocked{} 0 # TYPE vmod_redis_commands_total counter vmod_redis_commands_total{} 0 # TYPE vmod_redis_commands_failed counter vmod_redis_commands_failed{} 0 # TYPE vmod_redis_commands_retried counter vmod_redis_commands_retried{} 0 # TYPE vmod_redis_commands_error counter vmod_redis_commands_error{} 0 # TYPE vmod_redis_commands_noscript counter vmod_redis_commands_noscript{} 0 # TYPE vmod_redis_cluster_discoveries_total counter vmod_redis_cluster_discoveries_total{} 0 # TYPE vmod_redis_cluster_discoveries_failed counter vmod_redis_cluster_discoveries_failed{} 0 # TYPE vmod_redis_cluster_replies_moved counter vmod_redis_cluster_replies_moved{} 0 # TYPE vmod_redis_cluster_replies_ask counter vmod_redis_cluster_replies_ask{} 0 } txreq -hdr "stream: 1" \ -hdr "prefix: foo_" \ -hdr "default-labels: 1" \ -hdr {extra-labels: this="bar",that="baz"} rxresp expect resp.body == {# TYPE foo_servers_total counter foo_servers_total{this="bar",that="baz",name="db"} 1 # TYPE foo_servers_failed counter foo_servers_failed{this="bar",that="baz",name="db"} 0 # TYPE foo_connections_total counter foo_connections_total{this="bar",that="baz",name="db"} 0 # TYPE foo_connections_failed counter foo_connections_failed{this="bar",that="baz",name="db"} 0 # TYPE foo_connections_dropped counter foo_connections_dropped{this="bar",that="baz",name="db",reason="error"} 0 foo_connections_dropped{this="bar",that="baz",name="db",reason="hung_up"} 0 foo_connections_dropped{this="bar",that="baz",name="db",reason="overflow"} 0 foo_connections_dropped{this="bar",that="baz",name="db",reason="ttl"} 0 foo_connections_dropped{this="bar",that="baz",name="db",reason="version"} 0 foo_connections_dropped{this="bar",that="baz",name="db",reason="sick"} 0 # TYPE foo_workers_blocked counter foo_workers_blocked{this="bar",that="baz",name="db"} 0 # TYPE foo_commands_total counter foo_commands_total{this="bar",that="baz",name="db"} 0 # TYPE foo_commands_failed counter foo_commands_failed{this="bar",that="baz",name="db"} 0 # TYPE foo_commands_retried counter foo_commands_retried{this="bar",that="baz",name="db"} 0 # TYPE foo_commands_error counter foo_commands_error{this="bar",that="baz",name="db"} 0 # TYPE foo_commands_noscript counter foo_commands_noscript{this="bar",that="baz",name="db"} 0 # TYPE foo_cluster_discoveries_total counter foo_cluster_discoveries_total{this="bar",that="baz",name="db"} 0 # TYPE foo_cluster_discoveries_failed counter foo_cluster_discoveries_failed{this="bar",that="baz",name="db"} 0 # TYPE foo_cluster_replies_moved counter foo_cluster_replies_moved{this="bar",that="baz",name="db"} 0 # TYPE foo_cluster_replies_ask counter foo_cluster_replies_ask{this="bar",that="baz",name="db"} 0 } } -run varnish v1 -expect client_req == 2 libvmod-redis-21.0/src/tests/standalone.proxied-methods.vtc000066400000000000000000000126331476735432100241260ustar00rootroot00000000000000varnishtest "Tests proxied methods" server s1 { rxreq txresp } -repeat 1 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new master1 = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); new master2 = redis.db( location="${redis_master2_ip}:${redis_master2_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); } sub vcl_deliver { # SET (master1) -> GET (master1) -> GET (master2). redis.use("master1"); redis.command("SET"); redis.push("foo"); redis.push("Hello world!"); redis.execute(true); redis.command("GET"); redis.push("foo"); redis.execute(true); set resp.http.Reply-1 = redis.get_reply(); redis.command("GET", db="master2"); redis.push("foo", db="master2"); redis.execute(true, db="master2"); set resp.http.Reply-2 = redis.get_reply(db="master2"); # SET (master2) -> GET (master2) -> GET (master1). redis.use("master2"); redis.command("SET"); redis.push("bar"); redis.push("Hello world!"); redis.execute(true); redis.command("GET"); redis.push("bar"); redis.execute(true); set resp.http.Reply-3 = redis.get_reply(); redis.command("GET", db="master1"); redis.push("bar", db="master1"); redis.execute(true, db="master1"); set resp.http.Reply-4 = redis.get_reply(db="master1"); # same, with easy_execute # SET (master1) -> GET (master1) -> GET (master2). redis.use("master1"); redis.easy_execute("SET", "baz", "42"); redis.easy_execute("GET", "baz"); set resp.http.Reply-easy-1 = redis.get_reply(); redis.easy_execute("GET", "baz", db="master2", master = true); set resp.http.Reply-easy-2 = redis.get_reply(db="master2"); # SET (master2) -> GET (master2) -> GET (master1). redis.use("master2"); redis.easy_execute("SET", "qux", "42"); redis.command("GET"); redis.easy_execute("GET", "qux"); set resp.http.Reply-easy-3 = redis.get_reply(); redis.easy_execute("GET", "qux", db="master1"); set resp.http.Reply-easy-4 = redis.get_reply(db="master1"); # Stats. set resp.http.master1-stats = redis.stats(db="master1"); set resp.http.master1-servers-total = redis.counter("servers.total", db="master1"); redis.use("master1"); set resp.http.master1-connections-total = redis.counter("connections.total"); set resp.http.master1-connections-dropped-overflow = redis.counter("connections.dropped.overflow"); set resp.http.master1-commands-total = redis.counter("commands.total"); set resp.http.master1-commands-error = redis.counter("commands.error"); set resp.http.master1-commands-noscript = redis.counter("commands.noscript"); set resp.http.master2-stats = redis.stats(db="master2"); set resp.http.master2-servers-total = redis.counter("servers.total", db="master2"); redis.use("master2"); set resp.http.master2-connections-dropped-overflow = redis.counter("connections.dropped.overflow"); set resp.http.master2-connections-total = redis.counter("connections.total"); set resp.http.master2-commands-total = redis.counter("commands.total"); set resp.http.master2-commands-error = redis.counter("commands.error"); set resp.http.master2-commands-noscript = redis.counter("commands.noscript"); } } -start client c1 { txreq rxresp expect resp.http.Reply-1 == "Hello world!" expect resp.http.Reply-2 == "" expect resp.http.Reply-3 == "Hello world!" expect resp.http.Reply-4 == "" expect resp.http.Reply-easy-1 == "42" expect resp.http.Reply-easy-2 == "" expect resp.http.Reply-easy-3 == "42" expect resp.http.Reply-easy-4 == "" expect resp.http.master1-servers-total == "1" expect resp.http.master1-connections-total == "3" expect resp.http.master1-connections-dropped-overflow == "2" expect resp.http.master1-commands-total == "6" expect resp.http.master1-commands-error == "0" expect resp.http.master1-commands-noscript == "0" expect resp.http.master2-servers-total == "1" expect resp.http.master2-connections-total == "2" expect resp.http.master2-connections-dropped-overflow == "2" expect resp.http.master2-commands-total == "6" expect resp.http.master2-commands-error == "0" expect resp.http.master2-commands-noscript == "0" } -run varnish v1 -expect client_req == 1 libvmod-redis-21.0/src/tests/standalone.subnets-using-private-pool.vtc000066400000000000000000000052721476735432100262410ustar00rootroot00000000000000varnishtest "Tests subnets using private pool" server s1 { rxreq txresp } -repeat 1 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={" 1 ${redis_slave1_1_ip}/32, 0 ${redis_slave1_2_ip}/32 "}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=2, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); db.add_server("${redis_slave1_1_ip}:${redis_slave1_1_port}", slave); db.add_server("${redis_slave1_2_ip}:${redis_slave1_2_port}", slave); } sub vcl_deliver { # INFO (master). db.command("INFO"); db.execute(true); if (db.reply_is_string()) { set resp.http.Reply-1 = regsub( db.get_string_reply(), "(?s)^.*\nrole:([^\s]+)\s.*$", "\1"); set resp.http.Reply-2 = regsub( db.get_string_reply(), "(?s)^.*\ntcp_port:([^\s]+)\s.*$", "\1"); } # INFO (slave). db.command("INFO"); db.execute(false); if (db.reply_is_string()) { set resp.http.Reply-3 = regsub( db.get_string_reply(), "(?s)^.*\nrole:([^\s]+)\s.*$", "\1"); set resp.http.Reply-4 = regsub( db.get_string_reply(), "(?s)^.*\ntcp_port:([^\s]+)\s.*$", "\1"); } # Stats. set resp.http.db-stats = db.stats(); set resp.http.db-servers-total = db.counter("servers.total"); set resp.http.db-connections-total = db.counter("connections.total"); set resp.http.db-commands-total = db.counter("commands.total"); set resp.http.db-commands-error = db.counter("commands.error"); } } -start client c1 { txreq rxresp expect resp.http.Reply-1 == "master" expect resp.http.Reply-2 == "${redis_master1_port}" expect resp.http.Reply-3 == "slave" expect resp.http.Reply-4 == "${redis_slave1_2_port}" expect resp.http.db-servers-total == "3" expect resp.http.db-connections-total == "2" expect resp.http.db-commands-total == "2" expect resp.http.db-commands-error == "0" } -run varnish v1 -expect client_req == 1 libvmod-redis-21.0/src/tests/standalone.subnets-using-shared-pool.vtc000066400000000000000000000052701476735432100260330ustar00rootroot00000000000000varnishtest "Tests subnets using shared pool" server s1 { rxreq txresp } -repeat 1 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={" 1 ${redis_slave1_1_ip}/32, 0 ${redis_slave1_2_ip}/32 "}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=true, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); db.add_server("${redis_slave1_1_ip}:${redis_slave1_1_port}", slave); db.add_server("${redis_slave1_2_ip}:${redis_slave1_2_port}", slave); } sub vcl_deliver { # INFO (master). db.command("INFO"); db.execute(true); if (db.reply_is_string()) { set resp.http.Reply-1 = regsub( db.get_string_reply(), "(?s)^.*\nrole:([^\s]+)\s.*$", "\1"); set resp.http.Reply-2 = regsub( db.get_string_reply(), "(?s)^.*\ntcp_port:([^\s]+)\s.*$", "\1"); } # INFO (slave). db.command("INFO"); db.execute(false); if (db.reply_is_string()) { set resp.http.Reply-3 = regsub( db.get_string_reply(), "(?s)^.*\nrole:([^\s]+)\s.*$", "\1"); set resp.http.Reply-4 = regsub( db.get_string_reply(), "(?s)^.*\ntcp_port:([^\s]+)\s.*$", "\1"); } # Stats. set resp.http.db-stats = db.stats(); set resp.http.db-servers-total = db.counter("servers.total"); set resp.http.db-connections-total = db.counter("connections.total"); set resp.http.db-commands-total = db.counter("commands.total"); set resp.http.db-commands-error = db.counter("commands.error"); } } -start client c1 { txreq rxresp expect resp.http.Reply-1 == "master" expect resp.http.Reply-2 == "${redis_master1_port}" expect resp.http.Reply-3 == "slave" expect resp.http.Reply-4 == "${redis_slave1_2_port}" expect resp.http.db-servers-total == "3" expect resp.http.db-connections-total == "2" expect resp.http.db-commands-total == "2" expect resp.http.db-commands-error == "0" } -run varnish v1 -expect client_req == 1 libvmod-redis-21.0/src/tests/standalone.template.vtc000066400000000000000000000025211476735432100226210ustar00rootroot00000000000000varnishtest "Minimal test template" server s1 { rxreq txresp } -repeat 1 -start varnish v1 -arg "-p vsl_reclen=1024" -vcl+backend { import ${vmod_redis}; sub vcl_init { redis.subnets( masks={""}); redis.sentinels( locations={""}, period=0, connection_timeout=500, command_timeout=0); new db = redis.db( location="${redis_master1_ip}:${redis_master1_port}", type=master, connection_timeout=500, connection_ttl=0, command_timeout=0, max_command_retries=0, shared_connections=false, max_connections=1, password="", sickness_ttl=0, ignore_slaves=false, max_cluster_hops=0); } sub vcl_deliver { # Stats. set resp.http.db-stats = db.stats(); set resp.http.db-servers-total = db.counter("servers.total"); set resp.http.db-connections-total = db.counter("connections.total"); set resp.http.db-commands-total = db.counter("commands.total"); } } -start client c1 { txreq rxresp expect resp.http.db-servers-total == "1" expect resp.http.db-connections-total == "0" expect resp.http.db-commands-total == "0" } -run varnish v1 -expect client_req == 1 libvmod-redis-21.0/src/vmod_redis.c000066400000000000000000001636461476735432100173160ustar00rootroot00000000000000#include "config.h" #include #include #include #include #include #include #ifdef TLS_ENABLED #include #endif #include #ifdef __FreeBSD__ #include #endif #include "cache/cache.h" #include "vsb.h" #include "vcl.h" #include "vcc_redis_if.h" #ifdef TLS_ENABLED #ifdef HAVE_LIBVARNISH_SSLHELPER #include #endif #endif #include "cluster.h" #include "core.h" #include "sentinel.h" static task_state_t *get_task_state(VRT_CTX, struct vmod_priv *task_priv, unsigned flush); static void flush_task_state(task_state_t *state); static enum REDIS_SERVER_ROLE type2role(VCL_ENUM type); static enum REDIS_PROTOCOL parse_protocol(VCL_ENUM protocol); static const char *get_reply(VRT_CTX, redisReply *reply); /****************************************************************************** * VMOD EVENTS. *****************************************************************************/ static void fini_vcl_state(VRT_CTX, void *ptr) { free_vcl_state(ptr); } static const struct vmod_priv_methods vcl_state_priv_methods[1] = {{ .magic = VMOD_PRIV_METHODS_MAGIC, .type = "vcl_state", .fini = (vmod_priv_fini_f *)fini_vcl_state }}; static int handle_vcl_load_event(VRT_CTX, struct vmod_priv *vcl_priv) { // Initialize Varnish locks. if (vmod_state.locks.refs == 0) { vmod_state.locks.config = Lck_CreateClass( &vmod_state.locks.vsc_seg, "redis.config"); AN(vmod_state.locks.config); vmod_state.locks.db = Lck_CreateClass( &vmod_state.locks.vsc_seg, "redis.db"); AN(vmod_state.locks.db); } vmod_state.locks.refs++; // Initialize configuration in the local VCL data structure. vcl_priv->priv = new_vcl_state(); vcl_priv->methods = vcl_state_priv_methods; #ifdef TLS_ENABLED // Ensure OpenSSL global state is initialized only once. #ifdef HAVE_LIBVARNISH_SSLHELPER AN(VSSLH_status()); #else static int openssl_initialized = 0; if (!openssl_initialized) { openssl_initialized = 1; redisInitOpenSSL(); } #endif #endif // Done! return 0; } static int handle_vcl_warm_event(VRT_CTX, vcl_state_t *config) { // Increase global version AZ(pthread_mutex_lock(&vmod_state.mutex)); vmod_state.version++; AZ(pthread_mutex_unlock(&vmod_state.mutex)); // Start Sentinel thread? Lck_Lock(&config->mutex); if ((config->sentinels.locations != NULL) && (!config->sentinels.active)) { unsafe_sentinel_start(config); } Lck_Unlock(&config->mutex); // Done! return 0; } static int handle_vcl_cold_event(VRT_CTX, vcl_state_t *config) { // If required, stop Sentinel thread and wait for termination. This // guarantees the Sentinel thread won't loose the config reference // in its internal state unexpectedly. Lck_Lock(&config->mutex); if (config->sentinels.active) { unsafe_sentinel_stop(config); Lck_Unlock(&config->mutex); AN(config->sentinels.thread); AZ(pthread_join(config->sentinels.thread, NULL)); config->sentinels.thread = 0; } else { Lck_Unlock(&config->mutex); } // Iterate through registered database instances and close connections in // shared pools. Connections binded to worker threads cannot be closed // this way. unsigned dbs = 0; unsigned connections = 0; Lck_Lock(&config->mutex); database_t *idb; VTAILQ_FOREACH(idb, &config->dbs, list) { // Assertions. CHECK_OBJ_NOTNULL(idb, DATABASE_MAGIC); // Initializations. dbs++; // Get database lock. Lck_Lock(&idb->db->mutex); // Release contexts in all pools. for (unsigned iweight = 0; iweight < NREDIS_SERVER_WEIGHTS; iweight++) { for (enum REDIS_SERVER_ROLE irole = 0; irole < NREDIS_SERVER_ROLES; irole++) { redis_server_t *iserver; VTAILQ_FOREACH(iserver, &(idb->db->servers[iweight][irole]), list) { // Assertions. CHECK_OBJ_NOTNULL(iserver, REDIS_SERVER_MAGIC); // Release all contexts (both free an busy; this method is // assumed to be called when threads are not using the pool). iserver->pool.ncontexts = 0; redis_context_t *icontext; while (!VTAILQ_EMPTY(&iserver->pool.free_contexts)) { icontext = VTAILQ_FIRST(&iserver->pool.free_contexts); CHECK_OBJ_NOTNULL(icontext, REDIS_CONTEXT_MAGIC); connections++; VTAILQ_REMOVE(&iserver->pool.free_contexts, icontext, list); free_redis_context(icontext); } while (!VTAILQ_EMPTY(&iserver->pool.busy_contexts)) { icontext = VTAILQ_FIRST(&iserver->pool.busy_contexts); CHECK_OBJ_NOTNULL(icontext, REDIS_CONTEXT_MAGIC); connections++; VTAILQ_REMOVE(&iserver->pool.busy_contexts, icontext, list); free_redis_context(icontext); } } } } // Release database lock. Lck_Unlock(&idb->db->mutex); } Lck_Unlock(&config->mutex); REDIS_LOG_INFO(ctx, "Released %d pooled connections in %d database objects", connections, dbs); // Done! return 0; } static int handle_vcl_discard_event(VRT_CTX, vcl_state_t *config) { // Assertions. assert(vmod_state.locks.refs > 0); // Release Varnish locks. vmod_state.locks.refs--; if (vmod_state.locks.refs == 0) { Lck_DestroyClass(&vmod_state.locks.vsc_seg); } // Done! return 0; } int vmod_event_function(VRT_CTX, struct vmod_priv *vcl_priv, enum vcl_event_e e) { // Log event. const char *name; switch (e) { case VCL_EVENT_LOAD: name = "load"; break; case VCL_EVENT_WARM: name = "warm"; break; case VCL_EVENT_COLD: name = "cold"; break; case VCL_EVENT_DISCARD: name = "discard"; break; default: name = "-"; } REDIS_LOG_INFO(ctx, "VCL event triggered (event=%s)", name); // Route event. switch (e) { case VCL_EVENT_LOAD: return handle_vcl_load_event(ctx, vcl_priv); case VCL_EVENT_WARM: AN(vcl_priv->priv); return handle_vcl_warm_event(ctx, vcl_priv->priv); case VCL_EVENT_COLD: AN(vcl_priv->priv); return handle_vcl_cold_event(ctx, vcl_priv->priv); case VCL_EVENT_DISCARD: AN(vcl_priv->priv); return handle_vcl_discard_event(ctx, vcl_priv->priv); default: return 0; } } /****************************************************************************** * redis.subnets(); *****************************************************************************/ static void unsafe_set_subnets(VRT_CTX, vcl_state_t *config, const char *masks) { // Assertions. Lck_AssertHeld(&config->mutex); // Initializations unsigned error = 0; // Parse input. const char *p = masks; while (*p != '\0') { // Initializations. const char *q; // Parse weight. int weight = strtoul(p, (char **)&q, 10); if ((p == q) || (weight < 0) || (weight >= NREDIS_SERVER_WEIGHTS)) { error = 10; break; } // Parse address in the mask. char address[32]; p = q; while (isspace(*p)) p++; q = p; while (*q != '\0' && *q != '/') { q++; } if ((p == q) || (*q != '/') || (q - p >= sizeof(address))) { error = 20; break; } memcpy(address, p, q - p); address[q - p] = '\0'; struct in_addr ia4; if (inet_pton(AF_INET, address, &ia4) == 0) { error = 30; break; } // Parse number of bits in the mask. p = q + 1; if (!isdigit(*p)) { error = 40; break; } int bits = strtoul(p, (char **)&q, 10); if ((p == q) || (bits < 0) || (bits > 32)) { error = 50; break; } // Store parsed subnet. subnet_t *subnet = new_subnet(weight, ia4, bits); VTAILQ_INSERT_TAIL(&config->subnets, subnet, list); // More items? p = q; while (isspace(*p) || (*p == ',')) p++; } // Check error flag. if (error) { // Release parsed subnets. subnet_t *isubnet; while (!VTAILQ_EMPTY(&config->subnets)) { isubnet = VTAILQ_FIRST(&config->subnets); CHECK_OBJ_NOTNULL(isubnet, SUBNET_MAGIC); VTAILQ_REMOVE(&config->subnets, isubnet, list); free_subnet(isubnet); } // Log error. REDIS_LOG_ERROR(ctx, "Got error while parsing subnets (error=%d, masks=%s)", error, masks); } } VCL_VOID vmod_subnets(VRT_CTX, struct vmod_priv *vcl_priv, VCL_STRING masks) { // Initializations. vcl_state_t *config = vcl_priv->priv; // Get configuration lock. Lck_Lock(&config->mutex); // Silently ignore calls to this function if any database instance has // already been registered. if (VTAILQ_EMPTY(&config->dbs)) { // Do not continue if subnets have already been set. if (VTAILQ_EMPTY(&config->subnets)) { const char *value = NULL; if ((masks != NULL) && (strlen(masks) > 0)) { value = masks; } else { value = getenv("VMOD_REDIS_SUBNETS"); } if ((value != NULL) && (strlen(value) > 0)) { unsafe_set_subnets(ctx, config, value); } } else { REDIS_LOG_ERROR(ctx, "%s already set", "Subnets"); } } // Release configuration lock. Lck_Unlock(&config->mutex); } /****************************************************************************** * redis.sentinels(); *****************************************************************************/ VCL_VOID vmod_sentinels( VRT_CTX, struct vmod_priv *vcl_priv, VCL_STRING locations, VCL_INT period, VCL_INT connection_timeout, VCL_INT command_timeout, VCL_ENUM protocol, VCL_BOOL tls, VCL_STRING tls_cafile, VCL_STRING tls_capath, VCL_STRING tls_certfile, VCL_STRING tls_keyfile, VCL_STRING tls_sni, VCL_STRING password) { // Initializations. vcl_state_t *config = vcl_priv->priv; #ifndef RESP3_ENABLED // Abort if RESP3 is not available. if (protocol == enum_vmod_redis_RESP3) { REDIS_LOG_ERROR(ctx, "%s is not supported", "RESP3"); return; } #endif #ifndef TLS_ENABLED // Abort if TLS is not enabled. if (tls) { REDIS_LOG_ERROR(ctx, "%s is not supported", "TLS"); return; } #endif // Get configuration lock. Lck_Lock(&config->mutex); // Do not continue if Sentinels have already been set. if (config->sentinels.locations == NULL) { if ((connection_timeout >= 0) && (command_timeout >= 0)) { // Store settings. const char *value = NULL; if ((locations != NULL) && (strlen(locations) > 0)) { value = locations; } else { value = getenv("VMOD_REDIS_SENTINELS"); } if ((value != NULL) && (strlen(value) > 0)) { config->sentinels.locations = strdup(value); AN(config->sentinels.locations); config->sentinels.period = period; config->sentinels.connection_timeout.tv_sec = connection_timeout / 1000; config->sentinels.connection_timeout.tv_usec = (connection_timeout % 1000) * 1000; config->sentinels.command_timeout.tv_sec = command_timeout / 1000; config->sentinels.command_timeout.tv_usec = (command_timeout % 1000) * 1000; config->sentinels.protocol = parse_protocol(protocol); #ifdef TLS_ENABLED config->sentinels.tls = tls; if ((tls_cafile != NULL) && (strlen(tls_cafile) > 0)) { config->sentinels.tls_cafile = strdup(tls_cafile); AN(config->sentinels.tls_cafile); } if ((tls_capath != NULL) && (strlen(tls_capath) > 0)) { config->sentinels.tls_capath = strdup(tls_capath); AN(config->sentinels.tls_capath); } if ((tls_certfile != NULL) && (strlen(tls_certfile) > 0)) { config->sentinels.tls_certfile = strdup(tls_certfile); AN(config->sentinels.tls_certfile); } if ((tls_keyfile != NULL) && (strlen(tls_keyfile) > 0)) { config->sentinels.tls_keyfile = strdup(tls_keyfile); AN(config->sentinels.tls_keyfile); } if ((tls_sni != NULL) && (strlen(tls_sni) > 0)) { config->sentinels.tls_sni = strdup(tls_sni); AN(config->sentinels.tls_sni); } #endif if ((password != NULL) && (strlen(password) > 0)) { config->sentinels.password = strdup(password); AN(config->sentinels.password); } } // If required, startup of the Sentinel thread and execution of // the initial discovery will be triggered during 'warm' event. // That cannot be done here because execution of logic in // 'vcl_init' after a 'load' event is not necessarily followed // by a 'warm' event. } } else { REDIS_LOG_ERROR(ctx, "%s already set", "Sentinels"); } // Release configuration lock. Lck_Unlock(&config->mutex); } /****************************************************************************** * DB OBJECT. *****************************************************************************/ VCL_VOID vmod_db__init( VRT_CTX, struct vmod_redis_db **db, const char *vcl_name, struct vmod_priv *vcl_priv, VCL_STRING location, VCL_ENUM type, VCL_INT connection_timeout, VCL_INT connection_ttl, VCL_INT command_timeout, VCL_INT max_command_retries, VCL_BOOL shared_connections, VCL_INT max_connections, VCL_ENUM protocol, VCL_BOOL tls, VCL_STRING tls_cafile, VCL_STRING tls_capath, VCL_STRING tls_certfile, VCL_STRING tls_keyfile, VCL_STRING tls_sni, VCL_STRING user, VCL_STRING password, VCL_INT sickness_ttl, VCL_BOOL ignore_slaves, VCL_INT max_cluster_hops) { // Assert input. CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); AN(db); AZ(*db); #ifndef RESP3_ENABLED // Abort if RESP3 is not available. if (protocol == enum_vmod_redis_RESP3) { REDIS_LOG_ERROR(ctx, "%s is not supported", "RESP3"); return; } #endif #ifndef TLS_ENABLED // Abort if TLS is not enabled. if (tls) { REDIS_LOG_ERROR(ctx, "%s is not supported", "TLS"); return; } #endif // Check input. if ((connection_timeout >= 0) && (connection_ttl >= 0) && (command_timeout >= 0) && (max_command_retries >= 0) && (max_connections >= 0) && #ifdef TLS_ENABLED (tls_cafile != NULL) && (tls_capath != NULL) && (tls_certfile != NULL) && (tls_keyfile != NULL) && (tls_sni != NULL) && #endif (user != NULL) && (password != NULL) && (sickness_ttl >= 0) && (max_cluster_hops >= 0)) { // Initializations. vcl_state_t *config = vcl_priv->priv; struct timeval connection_timeout_tv; connection_timeout_tv.tv_sec = connection_timeout / 1000; connection_timeout_tv.tv_usec = (connection_timeout % 1000) * 1000; struct timeval command_timeout_tv; command_timeout_tv.tv_sec = command_timeout / 1000; command_timeout_tv.tv_usec = (command_timeout % 1000) * 1000; // Extract role & clustering flag. enum REDIS_SERVER_ROLE role = type2role(type); unsigned clustered = type == enum_vmod_redis_cluster; #ifdef TLS_ENABLED // Create Redis SSL context. redisSSLContext *tls_ssl_ctx = NULL; if (tls) { redisSSLContextError ssl_error; tls_ssl_ctx = redisCreateSSLContext( strlen(tls_cafile) > 0 ? tls_cafile : NULL, strlen(tls_capath) > 0 ? tls_capath : NULL, strlen(tls_certfile) > 0 ? tls_certfile : NULL, strlen(tls_keyfile) > 0 ? tls_keyfile : NULL, strlen(tls_sni) > 0 ? tls_sni : NULL, &ssl_error); if (tls_ssl_ctx == NULL) { REDIS_LOG_ERROR(ctx, "Failed to create SSL context: %s", redisSSLContextGetError(ssl_error)); return; } } #endif // Create new database instance. struct vmod_redis_db *instance = new_vmod_redis_db( config, vcl_name, connection_timeout_tv, connection_ttl, command_timeout_tv, max_command_retries, shared_connections, max_connections, parse_protocol(protocol), #ifdef TLS_ENABLED tls_ssl_ctx, #endif user, password, sickness_ttl, ignore_slaves, clustered, max_cluster_hops); // Add initial server if provided. if ((location != NULL) && (strlen(location) > 0)) { // Add initial server. Lck_Lock(&config->mutex); Lck_Lock(&instance->mutex); redis_server_t *server = unsafe_add_redis_server(ctx, instance, config, location, role); AN(server); Lck_Unlock(&instance->mutex); Lck_Unlock(&config->mutex); // Launch initial discovery of the cluster topology? This is not // required (i.e. it will be executed on demand) but it's a nice // thing to do while bootstrapping a new database instance. if (instance->cluster.enabled) { discover_cluster_slots(ctx, instance, config, server); } } // Register & return the new database instance. database_t *database = new_database(instance); Lck_Lock(&config->mutex); VTAILQ_INSERT_TAIL(&config->dbs, database, list); Lck_Unlock(&config->mutex); *db = instance; // Log event. REDIS_LOG_INFO(ctx, "New database instance registered (db=%s)", instance->name); } if (*db == NULL) { REDIS_FAIL_WS(ctx,); } } VCL_VOID vmod_db__fini(struct vmod_redis_db **db) { // Assert input. AN(db); AN(*db); // Log event. REDIS_LOG_INFO(NULL, "Unregistering database instance (db=%s)", (*db)->name); // Keep config reference before releasing the instance. vcl_state_t *config = (*db)->config; // Unregister database instance. Lck_Lock(&config->mutex); database_t *idb; VTAILQ_FOREACH(idb, &config->dbs, list) { CHECK_OBJ_NOTNULL(idb, DATABASE_MAGIC); if (idb->db == *db) { VTAILQ_REMOVE(&config->dbs, idb, list); free_database(idb); break; } } Lck_Unlock(&config->mutex); *db = NULL; } /****************************************************************************** * .add_server(); *****************************************************************************/ VCL_VOID vmod_db_add_server( VRT_CTX, struct vmod_redis_db *db, struct vmod_priv *vcl_priv, VCL_STRING location, VCL_ENUM type) { if ((location != NULL) && (strlen(location) > 0) && ((!db->cluster.enabled || type == enum_vmod_redis_cluster))) { // Initializations. vcl_state_t *config = vcl_priv->priv; enum REDIS_SERVER_ROLE role = type2role(type); // Add server. Lck_Lock(&config->mutex); Lck_Lock(&db->mutex); redis_server_t *server = unsafe_add_redis_server(ctx, db, config, location, role); AN(server); unsigned discovery = (server != NULL) && (db->cluster.enabled) && ((db->stats.cluster.discoveries.total - db->stats.cluster.discoveries.failed) == 0); Lck_Unlock(&db->mutex); Lck_Unlock(&config->mutex); // Launch initial discovery of the cluster topology? This flag has been // previously calculated while holding the appropriate locks. if (discovery) { discover_cluster_slots(ctx, db, config, server); } } } /****************************************************************************** * .command(); *****************************************************************************/ VCL_VOID vmod_db_command( VRT_CTX, struct vmod_redis_db *db, struct vmod_priv *task_priv, VCL_STRING name) { if ((name != NULL) && (strlen(name) > 0)) { // Fetch thread state & flush previous command. task_state_t *state = get_task_state(ctx, task_priv, 1); // Initialize. state->command.db = db; state->command.timeout = db->command_timeout; state->command.max_retries = db->max_command_retries; state->command.argc = 1; state->command.argv[0] = name; } } /****************************************************************************** * .timeout(); *****************************************************************************/ VCL_VOID vmod_db_timeout( VRT_CTX, struct vmod_redis_db *db, struct vmod_priv *task_priv, VCL_INT command_timeout) { // Fetch thread state. task_state_t *state = get_task_state(ctx, task_priv, 0); // Do not continue if the initial call to .command() was not executed // or if running this in a different database. if ((state->command.argc >= 1) && (state->command.db == db)) { state->command.timeout.tv_sec = command_timeout / 1000; state->command.timeout.tv_usec = (command_timeout % 1000) * 1000; } } /****************************************************************************** * .retries(); *****************************************************************************/ VCL_VOID vmod_db_retries( VRT_CTX, struct vmod_redis_db *db, struct vmod_priv *task_priv, VCL_INT max_command_retries) { // Fetch thread state. task_state_t *state = get_task_state(ctx, task_priv, 0); // Do not continue if the initial call to .command() was not executed // or if running this in a different database. if ((state->command.argc >= 1) && (state->command.db == db)) { state->command.max_retries = max_command_retries; } } /****************************************************************************** * .push(); *****************************************************************************/ VCL_VOID vmod_db_push( VRT_CTX, struct vmod_redis_db *db, struct vmod_priv *task_priv, VCL_STRING arg) { // Fetch thread state. task_state_t *state = get_task_state(ctx, task_priv, 0); // Do not continue if the maximum number of allowed arguments has been // reached or if the initial call to .command() was not executed or // if running this in a different database. if ((state->command.argc >= 1) && (state->command.argc < MAX_REDIS_COMMAND_ARGS) && (state->command.db == db)) { // Handle NULL arguments as empty strings. if (arg == NULL) { arg = WS_Copy(ctx->ws, "", -1); if (arg == NULL) { REDIS_FAIL_WS(ctx, ); } } state->command.argv[state->command.argc++] = arg; } else { REDIS_LOG_ERROR(ctx, "Failed to push argument (db=%s, limit=%d)", db->name, MAX_REDIS_COMMAND_ARGS); } } /****************************************************************************** * .execute(); *****************************************************************************/ VCL_VOID vmod_db_execute( VRT_CTX, struct vmod_redis_db *db, struct vmod_priv *vcl_priv, struct vmod_priv *task_priv, VCL_BOOL master) { // Fetch thread state. task_state_t *state = get_task_state(ctx, task_priv, 0); // Do not continue if the initial call to redis.command() was not executed // or if running this in a different database or if the workspace is // already overflowed. if ((state->command.argc >= 1) && (state->command.db == db)) { // Initializations. vcl_state_t *config = vcl_priv->priv; unsigned retries = 0; // Ignore slave servers if globally requested. if ((!master) && (db->ignore_slaves)) { master = 1; } // Force execution of LUA scripts in a master server when Redis Cluster // support is enabled. It's responsibility of the caller to avoid // execution of LUA scripts in slaves servers when clustering is // enabled. However, due it's counter-intuitiveness and the hidden and // expensive side effects (redirections followed by executions of // discoveries of the cluster topology) we enforce this here. if ((db->cluster.enabled) && (!master) && ((strcasecmp(state->command.argv[0], "EVAL") == 0) || (strcasecmp(state->command.argv[0], "EVALSHA") == 0))) { master = 1; } // Clustered vs. standalone execution. if (db->cluster.enabled) { state->command.reply = cluster_execute( ctx, db, config, state, state->command.timeout, state->command.max_retries, state->command.argc, state->command.argv, &retries, master); } else { state->command.reply = redis_execute( ctx, db, state, state->command.timeout, state->command.max_retries, state->command.argc, state->command.argv, &retries, NULL, 0, master, 0); } // Log error replies (other errors have already logged while executing // commands, retries, redirections, etc.). if ((state->command.reply != NULL) && (state->command.reply->type == REDIS_REPLY_ERROR)) { REDIS_LOG_ERROR(ctx, "Got error reply while executing command (command=%s, db=%s): %s", state->command.argv[0], db->name, state->command.reply->str); Lck_Lock(&db->mutex); db->stats.commands.error++; Lck_Unlock(&db->mutex); } } } /****************************************************************************** * .easy_execute(); *****************************************************************************/ #define HANDLE_ARG(N) \ if (args->valid_cmd_arg ## N) { \ vmod_db_push(ctx, db, args->task_priv, args->cmd_arg ## N); \ } /* we need this twice, with two different arg structures: * - one exposed directly by the vcc * - the other will be used by the proxied version * and sadly we can't use VMOD_PROXIED_METHOD because of this */ #define EASY_EXEC(name, arg_type) \ VCL_VOID \ name( \ VRT_CTX, struct vmod_redis_db *db, \ struct arg_type *args) \ { \ AN(ctx); \ AN(db); \ AN(args); \ AN(args->vcl_priv); \ AN(args->task_priv); \ \ vmod_db_command(ctx, db, args->task_priv, args->command); \ HANDLE_ARG(1); HANDLE_ARG(2); HANDLE_ARG(3); HANDLE_ARG(4); \ HANDLE_ARG(5); HANDLE_ARG(6); HANDLE_ARG(7); HANDLE_ARG(8); \ HANDLE_ARG(9); HANDLE_ARG(10); HANDLE_ARG(11); HANDLE_ARG(12); \ HANDLE_ARG(13); HANDLE_ARG(14); HANDLE_ARG(15); HANDLE_ARG(16); \ \ if (args->valid_timeout) { \ vmod_db_timeout(ctx, db, args->task_priv, args->timeout); \ } \ if (args->valid_retries) { \ vmod_db_retries(ctx, db, args->task_priv, args->retries); \ } \ \ vmod_db_execute(ctx, db, args->vcl_priv, args->task_priv, args->master); \ } EASY_EXEC(vmod_db_easy_execute, arg_vmod_redis_db_easy_execute); EASY_EXEC(vmod_db_easy_execute_proxy, arg_vmod_redis_easy_execute); #undef HANDLE_ARG /****************************************************************************** * .replied(); *****************************************************************************/ VCL_BOOL vmod_db_replied(VRT_CTX, struct vmod_redis_db *db, struct vmod_priv *task_priv) { task_state_t *state = get_task_state(ctx, task_priv, 0); return (state->command.db == db) && (state->command.reply != NULL); } /****************************************************************************** * .reply_is_error(); * .reply_is_nil(); * .reply_is_status(); * .reply_is_integer(); * .reply_is_boolean(); * .reply_is_double(); * .reply_is_string(); * .reply_is_array(); *****************************************************************************/ #define VMOD_DB_REPLY_IS_FOO(foo, condition) \ VCL_BOOL \ vmod_db_reply_is_ ## foo(VRT_CTX, struct vmod_redis_db *db, struct vmod_priv *task_priv) \ { \ task_state_t *state = get_task_state(ctx, task_priv, 0); \ return \ (state->command.db == db) && \ (state->command.reply != NULL) && \ (condition); \ } VMOD_DB_REPLY_IS_FOO( error, state->command.reply->type == REDIS_REPLY_ERROR) VMOD_DB_REPLY_IS_FOO( nil, state->command.reply->type == REDIS_REPLY_NIL) VMOD_DB_REPLY_IS_FOO( status, state->command.reply->type == REDIS_REPLY_STATUS) VMOD_DB_REPLY_IS_FOO( integer, state->command.reply->type == REDIS_REPLY_INTEGER) VMOD_DB_REPLY_IS_FOO( boolean, RESP3_SWITCH(state->command.reply->type == REDIS_REPLY_BOOL, 0)) VMOD_DB_REPLY_IS_FOO( double, RESP3_SWITCH(state->command.reply->type == REDIS_REPLY_DOUBLE, 0)) VMOD_DB_REPLY_IS_FOO( string, state->command.reply->type == REDIS_REPLY_STRING || RESP3_SWITCH(state->command.reply->type == REDIS_REPLY_VERB, 0)) VMOD_DB_REPLY_IS_FOO( array, state->command.reply->type == REDIS_REPLY_ARRAY || RESP3_SWITCH(state->command.reply->type == REDIS_REPLY_MAP, 0) || RESP3_SWITCH(state->command.reply->type == REDIS_REPLY_SET, 0)) /****************************************************************************** * .get_reply(); *****************************************************************************/ VCL_STRING vmod_db_get_reply(VRT_CTX, struct vmod_redis_db *db, struct vmod_priv *task_priv) { task_state_t *state = get_task_state(ctx, task_priv, 0); if ((state->command.db == db) && (state->command.reply != NULL)) { return get_reply(ctx, state->command.reply); } else { return NULL; } } /****************************************************************************** * .get_error_reply(); * .get_status_reply(); * .get_integer_reply(); * .get_boolean_reply(); * .get_double_reply(); * .get_string_reply(); *****************************************************************************/ #define VMOD_DB_GET_FOO_REPLY(type, foo, condition, field, fallback) \ VCL_ ## type \ vmod_db_get_ ## foo ## _reply(VRT_CTX, struct vmod_redis_db *db, struct vmod_priv *task_priv) \ { \ task_state_t *state = get_task_state(ctx, task_priv, 0); \ if ((state->command.db == db) && \ (state->command.reply != NULL) && \ (condition)) { \ return state->command.reply->field; \ } else { \ return fallback; \ } \ } VMOD_DB_GET_FOO_REPLY( INT, integer, state->command.reply->type == REDIS_REPLY_INTEGER, integer, 0) VMOD_DB_GET_FOO_REPLY( BOOL, boolean, RESP3_SWITCH(state->command.reply->type == REDIS_REPLY_BOOL, 0), integer, 0) VMOD_DB_GET_FOO_REPLY( REAL, double, RESP3_SWITCH(state->command.reply->type == REDIS_REPLY_DOUBLE, 0), RESP3_SWITCH(dval, integer), 0.0) #define VMOD_DB_GET_FOO_STRING_REPLY(foo, condition) \ VCL_STRING \ vmod_db_get_ ## foo ## _reply(VRT_CTX, struct vmod_redis_db *db, struct vmod_priv *task_priv) \ { \ task_state_t *state = get_task_state(ctx, task_priv, 0); \ if ((state->command.db == db) && \ (state->command.reply != NULL) && \ (condition)) { \ char *result = WS_Copy(ctx->ws, state->command.reply->str, state->command.reply->len + 1); \ if (result == NULL) { \ REDIS_FAIL_WS(ctx, NULL); \ } \ return result; \ } else { \ return NULL; \ } \ } VMOD_DB_GET_FOO_STRING_REPLY( error, state->command.reply->type == REDIS_REPLY_ERROR) VMOD_DB_GET_FOO_STRING_REPLY( status, state->command.reply->type == REDIS_REPLY_STATUS) VMOD_DB_GET_FOO_STRING_REPLY( string, state->command.reply->type == REDIS_REPLY_STRING || RESP3_SWITCH(state->command.reply->type == REDIS_REPLY_VERB, 0)) /****************************************************************************** * .get_array_reply_length(); *****************************************************************************/ VCL_INT vmod_db_get_array_reply_length( VRT_CTX, struct vmod_redis_db *db, struct vmod_priv *task_priv) { task_state_t *state = get_task_state(ctx, task_priv, 0); if ((state->command.db == db) && (state->command.reply != NULL) && (state->command.reply->type == REDIS_REPLY_ARRAY || RESP3_SWITCH(state->command.reply->type != REDIS_REPLY_MAP, 0) || RESP3_SWITCH(state->command.reply->type != REDIS_REPLY_SET, 0))) { return state->command.reply->elements; } else { return 0; } } /****************************************************************************** * .array_reply_is_error(); * .array_reply_is_nil(); * .array_reply_is_status(); * .array_reply_is_integer(); * .array_reply_is_boolean(); * .array_reply_is_double(); * .array_reply_is_string(); * .array_reply_is_array(); *****************************************************************************/ #define VMOD_DB_ARRAY_REPLY_IS_FOO(foo, condition) \ VCL_BOOL \ vmod_db_array_reply_is_ ## foo(VRT_CTX, struct vmod_redis_db *db, struct vmod_priv *task_priv, VCL_INT index) \ { \ task_state_t *state = get_task_state(ctx, task_priv, 0); \ return \ (state->command.db == db) && \ (state->command.reply != NULL) && \ (state->command.reply->type == REDIS_REPLY_ARRAY) && \ (index < state->command.reply->elements) && \ (condition); \ } VMOD_DB_ARRAY_REPLY_IS_FOO( error, state->command.reply->element[index]->type == REDIS_REPLY_ERROR) VMOD_DB_ARRAY_REPLY_IS_FOO( nil, state->command.reply->element[index]->type == REDIS_REPLY_NIL) VMOD_DB_ARRAY_REPLY_IS_FOO( status, state->command.reply->element[index]->type == REDIS_REPLY_STATUS) VMOD_DB_ARRAY_REPLY_IS_FOO( integer, state->command.reply->element[index]->type == REDIS_REPLY_INTEGER) VMOD_DB_ARRAY_REPLY_IS_FOO( boolean, RESP3_SWITCH(state->command.reply->element[index]->type == REDIS_REPLY_BOOL, 0)) VMOD_DB_ARRAY_REPLY_IS_FOO( double, RESP3_SWITCH(state->command.reply->element[index]->type == REDIS_REPLY_DOUBLE, 0)) VMOD_DB_ARRAY_REPLY_IS_FOO( string, state->command.reply->element[index]->type == REDIS_REPLY_STRING || RESP3_SWITCH(state->command.reply->element[index]->type == REDIS_REPLY_VERB, 0)) VMOD_DB_ARRAY_REPLY_IS_FOO( array, state->command.reply->element[index]->type == REDIS_REPLY_ARRAY || RESP3_SWITCH(state->command.reply->element[index]->type == REDIS_REPLY_MAP, 0) || RESP3_SWITCH(state->command.reply->element[index]->type == REDIS_REPLY_SET, 0)) /****************************************************************************** * .get_array_reply_value(); *****************************************************************************/ VCL_STRING vmod_db_get_array_reply_value( VRT_CTX, struct vmod_redis_db *db, struct vmod_priv *task_priv, VCL_INT index) { task_state_t *state = get_task_state(ctx, task_priv, 0); if ((state->command.db == db) && (state->command.reply != NULL) && (state->command.reply->type == REDIS_REPLY_ARRAY || RESP3_SWITCH(state->command.reply->type == REDIS_REPLY_MAP, 0) || RESP3_SWITCH(state->command.reply->type == REDIS_REPLY_SET, 0)) && (index < state->command.reply->elements)) { return get_reply(ctx, state->command.reply->element[index]); } else { return NULL; } } /****************************************************************************** * .free(); *****************************************************************************/ VCL_VOID vmod_db_free(VRT_CTX, struct vmod_redis_db *db, struct vmod_priv *task_priv) { get_task_state(ctx, task_priv, 1); } /****************************************************************************** * .stats(); *****************************************************************************/ VCL_STRING vmod_db_stats( VRT_CTX, struct vmod_redis_db *db, VCL_ENUM format, VCL_BOOL stream, VCL_STRING prometheus_name_prefix, VCL_BOOL prometheus_default_labels, VCL_STRING prometheus_extra_labels) { struct vsb *vsb = NULL; if (stream && ( (ctx->method == VCL_MET_SYNTH) || (ctx->method == VCL_MET_BACKEND_ERROR))) { CAST_OBJ_NOTNULL(vsb, ctx->specific, VSB_MAGIC); } else { stream = 0; vsb = VSB_new_auto(); AN(vsb); } Lck_Lock(&db->mutex); if (format == enum_vmod_redis_json) { AZ(VSB_printf(vsb, "{" "\"servers\": {" "\"total\": %" PRIu64 "," "\"failed\": %" PRIu64 "}," "\"connections\": {" "\"total\": %" PRIu64 "," "\"failed\": %" PRIu64 "," "\"dropped\": {" "\"error\": %" PRIu64 "," "\"hung_up\": %" PRIu64 "," "\"overflow\": %" PRIu64 "," "\"ttl\": %" PRIu64 "," "\"version\": %" PRIu64 "," "\"sick\": %" PRIu64 "}" "}," "\"workers\": {" "\"blocked\": %" PRIu64 "}," "\"commands\": {" "\"total\": %" PRIu64 "," "\"failed\": %" PRIu64 "," "\"retried\": %" PRIu64 "," "\"error\": %" PRIu64 "," "\"noscript\": %" PRIu64 "}," "\"cluster\": {" "\"discoveries\": {" "\"total\": %" PRIu64 "," "\"failed\": %" PRIu64 "}," "\"replies\": {" "\"moved\": %" PRIu64 "," "\"ask\": %" PRIu64 "}" "}" "}", db->stats.servers.total, db->stats.servers.failed, db->stats.connections.total, db->stats.connections.failed, db->stats.connections.dropped.error, db->stats.connections.dropped.hung_up, db->stats.connections.dropped.overflow, db->stats.connections.dropped.ttl, db->stats.connections.dropped.version, db->stats.connections.dropped.sick, db->stats.workers.blocked, db->stats.commands.total, db->stats.commands.failed, db->stats.commands.retried, db->stats.commands.error, db->stats.commands.noscript, db->stats.cluster.discoveries.total, db->stats.cluster.discoveries.failed, db->stats.cluster.replies.moved, db->stats.cluster.replies.ask)); } else if (format == enum_vmod_redis_prometheus) { // Beware: // - Some best practices (e.g. naming of metrics described in // https://prometheus.io/docs/practices/naming/#metric-names) are // not followed here for consistency with previously existing JSON // output. // - No validations or transformations are applied to metric names, // label names and label values in order to obey the data model // described in https://prometheus.io/docs/concepts/data_model/. const char *prefix = "vmod_redis_"; if ((prometheus_name_prefix != NULL) && (strlen(prometheus_name_prefix) > 0)) { prefix = prometheus_name_prefix; } const char *labels = WS_Printf(ctx->ws, "%s%s%s%s%s", ((prometheus_extra_labels != NULL) && (strlen(prometheus_extra_labels) > 0)) ? prometheus_extra_labels : "", ((prometheus_extra_labels != NULL) && (strlen(prometheus_extra_labels) > 0) && (prometheus_default_labels)) ? "," : "", (prometheus_default_labels) ? "name=\"" : "", (prometheus_default_labels) ? db->name : "", (prometheus_default_labels) ? "\"" : ""); if (labels == NULL) { if (!stream) { VSB_destroy(&vsb); } REDIS_FAIL_WS(ctx, NULL); } const char *separator = (strlen(labels) > 0) ? "," : ""; AZ(VSB_printf(vsb, "# TYPE %sservers_total counter\n" "%sservers_total{%s} %" PRIu64 "\n" "# TYPE %sservers_failed counter\n" "%sservers_failed{%s} %" PRIu64 "\n" "# TYPE %sconnections_total counter\n" "%sconnections_total{%s} %" PRIu64 "\n" "# TYPE %sconnections_failed counter\n" "%sconnections_failed{%s} %" PRIu64 "\n" "# TYPE %sconnections_dropped counter\n" "%sconnections_dropped{%s%sreason=\"error\"} %" PRIu64 "\n" "%sconnections_dropped{%s%sreason=\"hung_up\"} %" PRIu64 "\n" "%sconnections_dropped{%s%sreason=\"overflow\"} %" PRIu64 "\n" "%sconnections_dropped{%s%sreason=\"ttl\"} %" PRIu64 "\n" "%sconnections_dropped{%s%sreason=\"version\"} %" PRIu64 "\n" "%sconnections_dropped{%s%sreason=\"sick\"} %" PRIu64 "\n" "# TYPE %sworkers_blocked counter\n" "%sworkers_blocked{%s} %" PRIu64 "\n" "# TYPE %scommands_total counter\n" "%scommands_total{%s} %" PRIu64 "\n" "# TYPE %scommands_failed counter\n" "%scommands_failed{%s} %" PRIu64 "\n" "# TYPE %scommands_retried counter\n" "%scommands_retried{%s} %" PRIu64 "\n" "# TYPE %scommands_error counter\n" "%scommands_error{%s} %" PRIu64 "\n" "# TYPE %scommands_noscript counter\n" "%scommands_noscript{%s} %" PRIu64 "\n" "# TYPE %scluster_discoveries_total counter\n" "%scluster_discoveries_total{%s} %" PRIu64 "\n" "# TYPE %scluster_discoveries_failed counter\n" "%scluster_discoveries_failed{%s} %" PRIu64 "\n" "# TYPE %scluster_replies_moved counter\n" "%scluster_replies_moved{%s} %" PRIu64 "\n" "# TYPE %scluster_replies_ask counter\n" "%scluster_replies_ask{%s} %" PRIu64 "\n", prefix, prefix, labels, db->stats.servers.total, prefix, prefix, labels, db->stats.servers.failed, prefix, prefix, labels, db->stats.connections.total, prefix, prefix, labels, db->stats.connections.failed, prefix, prefix, labels, separator, db->stats.connections.dropped.error, prefix, labels, separator, db->stats.connections.dropped.hung_up, prefix, labels, separator, db->stats.connections.dropped.overflow, prefix, labels, separator, db->stats.connections.dropped.ttl, prefix, labels, separator, db->stats.connections.dropped.version, prefix, labels, separator, db->stats.connections.dropped.sick, prefix, prefix, labels, db->stats.workers.blocked, prefix, prefix, labels, db->stats.commands.total, prefix, prefix, labels, db->stats.commands.failed, prefix, prefix, labels, db->stats.commands.retried, prefix, prefix, labels, db->stats.commands.error, prefix, prefix, labels, db->stats.commands.noscript, prefix, prefix, labels, db->stats.cluster.discoveries.total, prefix, prefix, labels, db->stats.cluster.discoveries.failed, prefix, prefix, labels, db->stats.cluster.replies.moved, prefix, prefix, labels, db->stats.cluster.replies.ask)); } Lck_Unlock(&db->mutex); const char *result = NULL; if (stream) { result = WS_Copy(ctx->ws, "", -1); } else { AZ(VSB_putc(vsb, '\0')); AZ(VSB_finish(vsb)); result = WS_Copy(ctx->ws, VSB_data(vsb), VSB_len(vsb)); VSB_destroy(&vsb); } if (result == NULL) { REDIS_FAIL_WS(ctx, NULL); } return result; } /****************************************************************************** * .counter(); *****************************************************************************/ VCL_INT vmod_db_counter(VRT_CTX, struct vmod_redis_db *db, VCL_STRING name) { if (strcmp(name, "servers.total") == 0) { return db->stats.servers.total; } else if (strcmp(name, "servers.failed") == 0) { return db->stats.servers.failed; } else if (strcmp(name, "connections.total") == 0) { return db->stats.connections.total; } else if (strcmp(name, "connections.failed") == 0) { return db->stats.connections.failed; } else if (strcmp(name, "connections.dropped.error") == 0) { return db->stats.connections.dropped.error; } else if (strcmp(name, "connections.dropped.hung_up") == 0) { return db->stats.connections.dropped.hung_up; } else if (strcmp(name, "connections.dropped.overflow") == 0) { return db->stats.connections.dropped.overflow; } else if (strcmp(name, "connections.dropped.ttl") == 0) { return db->stats.connections.dropped.ttl; } else if (strcmp(name, "connections.dropped.version") == 0) { return db->stats.connections.dropped.version; } else if (strcmp(name, "connections.dropped.sick") == 0) { return db->stats.connections.dropped.sick; } else if (strcmp(name, "workers.blocked") == 0) { return db->stats.workers.blocked; } else if (strcmp(name, "commands.total") == 0) { return db->stats.commands.total; } else if (strcmp(name, "commands.failed") == 0) { return db->stats.commands.failed; } else if (strcmp(name, "commands.retried") == 0) { return db->stats.commands.retried; } else if (strcmp(name, "commands.error") == 0) { return db->stats.commands.error; } else if (strcmp(name, "commands.noscript") == 0) { return db->stats.commands.noscript; } else if (strcmp(name, "cluster.discoveries.total") == 0) { return db->stats.cluster.discoveries.total; } else if (strcmp(name, "cluster.discoveries.failed") == 0) { return db->stats.cluster.discoveries.failed; } else if (strcmp(name, "cluster.replies.moved") == 0) { return db->stats.cluster.replies.moved; } else if (strcmp(name, "cluster.replies.ask") == 0) { return db->stats.cluster.replies.ask; } else { REDIS_LOG_ERROR(ctx, "Failed to fetch counter (name=%s)", name); return 0; } } /****************************************************************************** * PROXY. *****************************************************************************/ static struct vmod_redis_db * get_db_instance(VRT_CTX, vcl_state_t *config, const char *db) { // Initializations. struct vmod_redis_db *result = NULL; // Search database instance. Lck_Lock(&config->mutex); database_t *idb; VTAILQ_FOREACH(idb, &config->dbs, list) { CHECK_OBJ_NOTNULL(idb, DATABASE_MAGIC); if (strcmp(idb->db->name, db) == 0) { result = idb->db; break; } } Lck_Unlock(&config->mutex); // Done! return result; } VCL_VOID vmod_use( VRT_CTX, struct vmod_priv *vcl_priv, struct vmod_priv *task_priv, VCL_STRING db) { // Fetch thread state & flush previous command. task_state_t *state = get_task_state(ctx, task_priv, 1); // Check input. if ((db != NULL) && (strlen(db) > 0)) { vcl_state_t *config = vcl_priv->priv; state->db = get_db_instance(ctx, config, db); } else { state->db = NULL; } // Log error? if (state->db == NULL) { REDIS_LOG_ERROR(ctx, "Failed to use database (db=%s)", db); } } VCL_VOID vmod_easy_execute(VRT_CTX, struct arg_vmod_redis_easy_execute *args) { struct vmod_redis_db *instance; AN(ctx); AN(args); AN(args->vcl_priv); AN(args->task_priv); if ((args->db != NULL) && (strlen(args->db) > 0)) { vcl_state_t *config = args->vcl_priv->priv; instance = get_db_instance(ctx, config, args->db); } else { task_state_t *state = get_task_state(ctx, args->task_priv, 0); instance = state->db; } if (instance != NULL) { return vmod_db_easy_execute_proxy(ctx, instance, args); } else { REDIS_LOG_ERROR(ctx, "Database instance not available%s", ""); return; } } #define _COMMA_ , #define VMOD_PROXIED_METHOD(type, fallback, method, margs, fargs...) \ VCL_ ## type \ vmod_ ## method(VRT_CTX, struct vmod_priv *vcl_priv, struct vmod_priv *task_priv, ##fargs, VCL_STRING db) \ { \ struct vmod_redis_db *instance; \ if ((db != NULL) && (strlen(db) > 0)) { \ vcl_state_t *config = vcl_priv->priv; \ instance = get_db_instance(ctx, config, db); \ } else { \ task_state_t *state = get_task_state(ctx, task_priv, 0); \ instance = state->db; \ } \ \ if (instance != NULL) { \ return vmod_db_ ## method(ctx, instance margs); \ } else { \ REDIS_LOG_ERROR(ctx, \ "Database instance not available%s", \ ""); \ return fallback; \ } \ } VMOD_PROXIED_METHOD( VOID, , add_server, _COMMA_ vcl_priv _COMMA_ location _COMMA_ type, VCL_STRING location, VCL_ENUM type) VMOD_PROXIED_METHOD( VOID, , command, _COMMA_ task_priv _COMMA_ name, VCL_STRING name) VMOD_PROXIED_METHOD( VOID, , timeout, _COMMA_ task_priv _COMMA_ command_timeout, VCL_INT command_timeout) VMOD_PROXIED_METHOD( VOID, , retries, _COMMA_ task_priv _COMMA_ max_command_retries, VCL_INT max_command_retries) VMOD_PROXIED_METHOD( VOID, , push, _COMMA_ task_priv _COMMA_ arg, VCL_STRING arg) VMOD_PROXIED_METHOD( VOID, , execute, _COMMA_ vcl_priv _COMMA_ task_priv _COMMA_ master, VCL_BOOL master) VMOD_PROXIED_METHOD( BOOL, 0, replied, _COMMA_ task_priv) VMOD_PROXIED_METHOD( BOOL, 0, reply_is_error, _COMMA_ task_priv) VMOD_PROXIED_METHOD( BOOL, 0, reply_is_nil, _COMMA_ task_priv) VMOD_PROXIED_METHOD( BOOL, 0, reply_is_status, _COMMA_ task_priv) VMOD_PROXIED_METHOD( BOOL, 0, reply_is_integer, _COMMA_ task_priv) VMOD_PROXIED_METHOD( BOOL, 0, reply_is_boolean, _COMMA_ task_priv) VMOD_PROXIED_METHOD( BOOL, 0, reply_is_double, _COMMA_ task_priv) VMOD_PROXIED_METHOD( BOOL, 0, reply_is_string, _COMMA_ task_priv) VMOD_PROXIED_METHOD( BOOL, 0, reply_is_array, _COMMA_ task_priv) VMOD_PROXIED_METHOD( STRING, NULL, get_reply, _COMMA_ task_priv) VMOD_PROXIED_METHOD( STRING, NULL, get_error_reply, _COMMA_ task_priv) VMOD_PROXIED_METHOD( STRING, NULL, get_status_reply, _COMMA_ task_priv) VMOD_PROXIED_METHOD( INT, 0, get_integer_reply, _COMMA_ task_priv) VMOD_PROXIED_METHOD( BOOL, 0, get_boolean_reply, _COMMA_ task_priv) VMOD_PROXIED_METHOD( REAL, 0, get_double_reply, _COMMA_ task_priv) VMOD_PROXIED_METHOD( STRING, NULL, get_string_reply, _COMMA_ task_priv) VMOD_PROXIED_METHOD( INT, 0, get_array_reply_length, _COMMA_ task_priv) VMOD_PROXIED_METHOD( BOOL, 0, array_reply_is_error, _COMMA_ task_priv _COMMA_ index, VCL_INT index) VMOD_PROXIED_METHOD( BOOL, 0, array_reply_is_nil, _COMMA_ task_priv _COMMA_ index, VCL_INT index) VMOD_PROXIED_METHOD( BOOL, 0, array_reply_is_status, _COMMA_ task_priv _COMMA_ index, VCL_INT index) VMOD_PROXIED_METHOD( BOOL, 0, array_reply_is_integer, _COMMA_ task_priv _COMMA_ index, VCL_INT index) VMOD_PROXIED_METHOD( BOOL, 0, array_reply_is_boolean, _COMMA_ task_priv _COMMA_ index, VCL_INT index) VMOD_PROXIED_METHOD( BOOL, 0, array_reply_is_double, _COMMA_ task_priv _COMMA_ index, VCL_INT index) VMOD_PROXIED_METHOD( BOOL, 0, array_reply_is_string, _COMMA_ task_priv _COMMA_ index, VCL_INT index) VMOD_PROXIED_METHOD( BOOL, 0, array_reply_is_array, _COMMA_ task_priv _COMMA_ index, VCL_INT index) VMOD_PROXIED_METHOD( STRING, NULL, get_array_reply_value, _COMMA_ task_priv _COMMA_ index, VCL_INT index) VMOD_PROXIED_METHOD( VOID, , free, _COMMA_ task_priv) VMOD_PROXIED_METHOD( STRING, NULL, stats, _COMMA_ format _COMMA_ stream _COMMA_ prometheus_name_prefix _COMMA_ prometheus_default_labels _COMMA_ prometheus_extra_labels, VCL_ENUM format, VCL_BOOL stream, VCL_STRING prometheus_name_prefix, VCL_BOOL prometheus_default_labels, VCL_STRING prometheus_extra_labels) VMOD_PROXIED_METHOD( INT, 0, counter, _COMMA_ name, VCL_STRING name) #undef _COMMA_ /****************************************************************************** * UTILITIES. *****************************************************************************/ static void fini_task_state(VRT_CTX, void *ptr) { free_task_state(ptr); } static const struct vmod_priv_methods task_state_priv_methods[1] = {{ .magic = VMOD_PRIV_METHODS_MAGIC, .type = "task_state", .fini = (vmod_priv_fini_f *)fini_task_state }}; static task_state_t * get_task_state(VRT_CTX, struct vmod_priv *task_priv, unsigned flush) { // Initializations. task_state_t *result = NULL; // Create thread state if not created yet. if (task_priv->priv == NULL) { task_priv->priv = new_task_state(); task_priv->methods = task_state_priv_methods; result = task_priv->priv; } else { result = task_priv->priv; CHECK_OBJ(result, TASK_STATE_MAGIC); } // Flush enqueued command? if (flush) { flush_task_state(result); } // Done! return result; } static void flush_task_state(task_state_t *state) { state->command.db = NULL; state->command.timeout = (struct timeval){ 0 }; state->command.max_retries = 0; state->command.argc = 0; if (state->command.reply != NULL) { freeReplyObject(state->command.reply); state->command.reply = NULL; } } static enum REDIS_SERVER_ROLE type2role(VCL_ENUM type) { enum REDIS_SERVER_ROLE result; if (type == enum_vmod_redis_master) { result = REDIS_SERVER_MASTER_ROLE; } else if (type == enum_vmod_redis_slave) { result = REDIS_SERVER_SLAVE_ROLE; } else if (type == enum_vmod_redis_auto) { result = REDIS_SERVER_TBD_ROLE; } else if (type == enum_vmod_redis_cluster) { result = REDIS_SERVER_TBD_ROLE; } else { WRONG("Invalid server type value."); } return result; } static enum REDIS_PROTOCOL parse_protocol(VCL_ENUM protocol) { enum REDIS_PROTOCOL result; if (protocol == enum_vmod_redis_default) { result = REDIS_PROTOCOL_DEFAULT; } else if (protocol == enum_vmod_redis_RESP2) { result = REDIS_PROTOCOL_RESP2; } else if (protocol == enum_vmod_redis_RESP3) { result = REDIS_PROTOCOL_RESP3; } else { WRONG("Invalid protocol value."); } return result; } static const char * get_reply(VRT_CTX, redisReply *reply) { // Default result. const char *result = NULL; // Check type of reply. switch (reply->type) { case REDIS_REPLY_ERROR: case REDIS_REPLY_STATUS: case REDIS_REPLY_STRING: #ifdef RESP3_ENABLED case REDIS_REPLY_VERB: case REDIS_REPLY_DOUBLE: #endif result = WS_Copy(ctx->ws, reply->str, reply->len + 1); if (result == NULL) { REDIS_FAIL_WS(ctx, NULL); } break; case REDIS_REPLY_INTEGER: #ifdef RESP3_ENABLED case REDIS_REPLY_BOOL: #endif result = WS_Printf(ctx->ws, "%lld", reply->integer); if (result == NULL) { REDIS_FAIL_WS(ctx, NULL); } break; case REDIS_REPLY_ARRAY: #ifdef RESP3_ENABLED case REDIS_REPLY_MAP: case REDIS_REPLY_SET: #endif // XXX: array, map & set replies are *not* supported. result = NULL; break; default: result = NULL; } // Done! return result; } libvmod-redis-21.0/src/vmod_redis.vcc000066400000000000000000000702041476735432100176320ustar00rootroot00000000000000# # Copyright (c) Carlos Abalde # # You're free to use and distribute this under terms in the # LICENSE file. # $Module redis 3 'Redis VMOD' $ABI strict DESCRIPTION =========== VMOD using the synchronous hiredis library API to access Redis servers from VCL. $Event event_function $Function VOID subnets(PRIV_VCL, STRING masks="") Arguments subnets: Comma-delimited list of weights + subnet masks used to select among servers associated to a database instance when executing commands. Order is relevant. Only IPv4 addresses are supported. If not provided, value in the VMOD_REDIS_SUBNETS environment variable will be used. This is useful in setups using Redis instances deployed across multiple data centers or availability zones. Description Using this function is not mandatory. If used, it must be called during ``vcl_init`` before creating any database instance. If a database instance has already been created calls to this function are silently ignored. $Function VOID sentinels(PRIV_VCL, STRING locations="", INT period=60, INT connection_timeout=500, INT command_timeout=0, ENUM { RESP2, RESP3, default } protocol="default", BOOL tls=0, STRING tls_cafile="", STRING tls_capath="", STRING tls_certfile="", STRING tls_keyfile="", STRING tls_sni="", STRING password="") Arguments locations: Comma-delimited list of Redis Sentinel servers. Only host (IP or DNS name) + port format is allowed. If not provided, value in the VMOD_REDIS_SENTINELS environment variable will be used. This is useful in setups using non-clustered Redis instances in order to (1) keep roles (i.e. master / slave) updated; and (2) decrease priority of unreachable servers when creating execution plans. This is **not** designed for auto-discovery of Redis Servers. period: how frequently (seconds) Redis Sentinel periodical checks are executed (0 means disabling periodical checks). Beware (1) proactive checks are also executed anytime the VCL state is changed to warm; and (2) Sentinel Pub/Sub events are listened and processed even when periodical checks are disabled. connection_timeout: connection timeout (milliseconds; 0 means no timeout) to the Redis Sentinel servers. command_timeout: command timeout (milliseconds; 0 means no timeout) when executing Redis Sentinel commands. protocol: protocol to be used when talking to Redis Sentinel servers. Beware switching from ``RESP2`` to ``RESP3`` is only possible since Redis 6.0 and it uses an additional ``HELLO`` command when creating new Redis Sentinel connections. Be careful ``RESP3`` support is only available since ``hiredis`` 0.15.0. tsl: if enabled, TLS will be used when establishing connections. tls_cafile: if not empty, this CA certificate file will be used to verify TLS connections. tls_capath: if not empty, this will be the directory storing trusted CA certificates used to verify TLS connections. If neither ``tls_cafile`` nor ``tls_capath`` are specified, the default system-wide trusted root certs configuration will apply. tls_certfile: if not empty, this certificate file will be used to authenticate TLS connections. tls_keyfile: if not empty, this private key file will be used to authenticate TLS connections. tls_sni: if not empty, this server name indication (i.e. SNI) will be used when establishing TLS connections. password: if not empty, requests for authentication using the ``AUTH`` command will be submitted when creating new Redis Sentinel connections. This password will be used for all Redis Sentinel servers. Description Using this function is not mandatory. $Function VOID use(PRIV_VCL, PRIV_TASK, STRING db) Arguments db: VCL name of the database instance. Description Sets the current database instance to be used by proxied methods (if none is specified with their ``db`` argument). $Function VOID add_server( PRIV_VCL, PRIV_TASK, STRING location, ENUM { master, slave, auto, cluster } type, STRING db="") Description Proxied version of ``.add_server()``. $Function VOID command(PRIV_VCL, PRIV_TASK, STRING name, STRING db="") Description Proxied version of ``.command()``. $Function VOID timeout(PRIV_VCL, PRIV_TASK, INT command_timeout, STRING db="") Description Proxied version of ``.timeout()``. $Function VOID retries(PRIV_VCL, PRIV_TASK, INT max_command_retries, STRING db="") Description Proxied version of ``.retries()``. $Function VOID push(PRIV_VCL, PRIV_TASK, STRING arg, STRING db="") Description Proxied version of ``.push()``. $Function VOID execute(PRIV_VCL, PRIV_TASK, BOOL master=1, STRING db="") Description Proxied version of ``.execute()``. $Function VOID easy_execute(PRIV_VCL vcl_priv, PRIV_TASK task_priv, STRING command, [STRING cmd_arg1], [STRING cmd_arg2], [STRING cmd_arg3], [STRING cmd_arg4], [STRING cmd_arg5], [STRING cmd_arg6], [STRING cmd_arg7], [STRING cmd_arg8], [STRING cmd_arg9], [STRING cmd_arg10], [STRING cmd_arg11], [STRING cmd_arg12], [STRING cmd_arg13], [STRING cmd_arg14], [STRING cmd_arg15], [STRING cmd_arg16], [INT timeout], [INT retries], BOOL master = 1, STRING db="" ) Description Proxied version of ``.easy_execute()``. $Function BOOL replied(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.replied()``. $Function BOOL reply_is_error(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.reply_is_error()``. $Function BOOL reply_is_nil(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.reply_is_nil()``. $Function BOOL reply_is_status(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.reply_is_status()``. $Function BOOL reply_is_integer(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.reply_is_integer()``. $Function BOOL reply_is_boolean(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.reply_is_boolean()``. $Function BOOL reply_is_double(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.reply_is_double()``. $Function BOOL reply_is_string(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.reply_is_string()``. $Function BOOL reply_is_array(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.reply_is_array()``. $Function STRING get_reply(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.get_reply()``. $Function STRING get_error_reply(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.get_error_reply()``. $Function STRING get_status_reply(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.get_status_reply()``. $Function INT get_integer_reply(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.get_integer_reply()``. $Function BOOL get_boolean_reply(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.get_boolean_reply()``. $Function REAL get_double_reply(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.get_double_reply()``. $Function STRING get_string_reply(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.get_string_reply()``. $Function INT get_array_reply_length(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.get_array_reply_length()``. $Function BOOL array_reply_is_error(PRIV_VCL, PRIV_TASK, INT index, STRING db="") Description Proxied version of ``.array_reply_is_error()``. $Function BOOL array_reply_is_nil(PRIV_VCL, PRIV_TASK, INT index, STRING db="") Description Proxied version of ``.array_reply_is_nil()``. $Function BOOL array_reply_is_status(PRIV_VCL, PRIV_TASK, INT index, STRING db="") Description Proxied version of ``.array_reply_is_status()``. $Function BOOL array_reply_is_integer(PRIV_VCL, PRIV_TASK, INT index, STRING db="") Description Proxied version of ``.array_reply_is_integer()``. $Function BOOL array_reply_is_boolean(PRIV_VCL, PRIV_TASK, INT index, STRING db="") Description Proxied version of ``.array_reply_is_boolean()``. $Function BOOL array_reply_is_double(PRIV_VCL, PRIV_TASK, INT index, STRING db="") Description Proxied version of ``.array_reply_is_double()``. $Function BOOL array_reply_is_string(PRIV_VCL, PRIV_TASK, INT index, STRING db="") Description Proxied version of ``.array_reply_is_string()``. $Function BOOL array_reply_is_array(PRIV_VCL, PRIV_TASK, INT index, STRING db="") Description Proxied version of ``.array_reply_is_array()``. $Function STRING get_array_reply_value(PRIV_VCL, PRIV_TASK, INT index, STRING db="") Description Proxied version of ``.get_array_reply_value()``. $Function VOID free(PRIV_VCL, PRIV_TASK, STRING db="") Description Proxied version of ``.free()``. $Function STRING stats(PRIV_VCL, PRIV_TASK, ENUM { json, prometheus } format="json", BOOL stream=0, STRING prometheus_name_prefix="vmod_redis_", BOOL prometheus_default_labels=1, STRING prometheus_extra_labels="", STRING db="") Description Proxied version of ``.stats()``. $Function INT counter(PRIV_VCL, PRIV_TASK, STRING name, STRING db="") Description Proxied version of ``.counter()``. $Object db(PRIV_VCL, STRING location="", ENUM { master, slave, auto, cluster } type="auto", INT connection_timeout=1000, INT connection_ttl=0, INT command_timeout=0, INT max_command_retries=0, BOOL shared_connections=1, INT max_connections=128, ENUM { RESP2, RESP3, default } protocol="default", BOOL tls=0, STRING tls_cafile="", STRING tls_capath="", STRING tls_certfile="", STRING tls_keyfile="", STRING tls_sni="", STRING user="", STRING password="", INT sickness_ttl=60, BOOL ignore_slaves=0, INT max_cluster_hops=32) Arguments location: Redis connection string. Both host (IP or DNS name) + port and UNIX sockets are supported. Only the IP + port format is allowed when Redis Cluster support is enabled. **Do not use DNS names in combination with ``redis.subnets()`` or ``redis.sentinels()``**. type: type of the Redis server referenced by ``location``: - The ``auto`` value enables automatic discovery of the current role of the server on bootstrap time using the ``ROLE`` command. - The ``cluster`` value enables Redis Cluster support, automatically discovering other servers in the cluster and their roles on demand using the ``CLUSTER SLOTS`` command. connection_timeout: connection timeout (milliseconds; 0 means no timeout) to the Redis server. connection_ttl: TTL (seconds) of Redis connections (0 means no TTL). Once the TTL of a connection is consumed, the module transparently reestablishes it. See "Client timeouts" in http://redis.io/topics/clients for extra information. command_timeout: command timeout (milliseconds; 0 means no timeout) when executing a Redis command. It can be overridden during command execution with ``.timeout()``. max_command_retries: number of retries to be executed after a failed command execution. It can be overridden during command execution with ``.retries()``. shared_connections: if enabled, Redis connections are not local to Varnish worker threads, but shared by all threads using one or more pools. max_connections: When ``shared_connections`` is enabled, the VMOD creates one pool of Redis connections per location and database instance. This option sets the maximum number of connections in each pool. All Varnish worker threads using the same database instance will share connections in these pools. Pools are not shared between database instances. Note that when Redis Cluster support is enabled for a database, each server is the cluster is internally labeled by the VMOD with its location (IP + port). When ``shared_connections`` is disabled, Redis connections are local to each Varnish worker thread. This option sets the maximum number of Redis connections per Varnish worker thread. Each thread keeps up to one connection per location and database instance. If more than one (database, location) pair is available, incrementing this limit allows recycling of Redis connections. WARNING: when creating multiple database instances, always use the same value in all instances using private connections. Otherwise you may experience inconsistent behavior. protocol: protocol to be used when talking to Redis Server servers. Beware switching from ``RESP2`` to ``RESP3`` is only possible since Redis 6.0 and it affects to type conversion rules. Be careful ``RESP3`` support is only available since ``hiredis`` 0.15.0. tsl: if enabled, TLS will be used when establishing connections. tls_cafile: if not empty, this CA certificate file will be used to verify TLS connections. tls_capath: if not empty, this will be the directory storing trusted CA certificates used to verify TLS connections. If neither ``tls_cafile`` nor ``tls_capath`` are specified, the default system-wide trusted root certs configuration will apply. tls_certfile: if not empty, this certificate file will be used to authenticate TLS connections. tls_keyfile: if not empty, this private key file will be used to authenticate TLS connections. tls_sni: if not empty, this server name indication (i.e. SNI) will be used when establishing TLS connections. user: if not empty and a ``password`` is provided, requests for authentication using the ``AUTH`` or ``HELLO`` command will include both the user name and its password. That enables usage of the Redis ACL system, available since Redis 6.0. password: if not empty, requests for authentication using the ``AUTH`` or ``HELLO`` command will be submitted when creating new Redis connections. This password will be used for all Redis servers, including discovered servers when Redis Cluster support is enabled. sickness_ttl: TTL (seconds) of the sickness flag (0 means no sickness flags) associated to a Redis server. Once a server is flagged as sick and while the flag is not expired the module will lazily drop existing connections to that server and it will try to avoid it as much as possible when creating execution plans. This TTL is overridden when Redis Sentinel servers are configured and some Sentinel discovers an unreachable server. ignore_slaves: if enabled, slave servers are not considered when executing commands. In other words, enabling this option implicitly forces ``master == true`` when using the ``.execute()`` method. max_cluster_hops: maximum number of redirections (0 means no limit) when executing a command and Redis Cluster support has been enabled. Description Creates a new database instance. $Method VOID .add_server( PRIV_VCL, STRING location, ENUM { master, slave, auto, cluster } type) Arguments location: Redis connection string. Both host (IP or DNS name) + port and UNIX sockets are supported. If Redis Cluster support has been enabled only the IP + port format is allowed. **Do not use DNS names in combination with ``redis.subnets()`` or ``redis.sentinels()``**. type: type of the Redis server referenced by ``location``: - The ``auto`` value enables automatic discovery of the current role of the server on bootstrap time using the ``ROLE`` command. - If Redis Cluster support has been enabled ``cluster`` is the only allowed value. Description Adds an extra Redis server. If Redis Cluster support has been enabled other servers in the cluster and their roles are automatically discovered by the VMOD using the ``CLUSTER SLOTS`` command. In any case, knowing more cluster servers during startup increases the chances of discover the cluster topology if some server is failing. $Method VOID .command(PRIV_TASK, STRING name) Arguments name: name of the Redis command to be executed. Description Enqueues a Redis command (only the name of the command) for further execution. Arguments should be enqueued separately calling one or more times to the ``.push()`` method. On execution time, ``EVAL`` commands are internally replace by ``EVALSHA`` commands, which fallback to the original ``EVAL`` command if the Redis server returns a ``NOSCRIPT`` error (see http://redis.io/commands/eval). $Method VOID .timeout(PRIV_TASK, INT command_timeout) Arguments command_timeout: command timeout (milliseconds; 0 means no timeout) to be used when executing a specific Redis command. Description Allows overriding the default command timeout provided when calling ``.db()``. $Method VOID .retries(PRIV_TASK, INT max_command_retries) Arguments max_command_retries: number of retries to be executed after a failed command execution. Description Allows overriding the default number of retries provided when calling ``.db()``. $Method VOID .push(PRIV_TASK, STRING arg) Arguments arg: argument of a previously enqueued Redis command. Description Provides an argument to a previously enqueued Redis command. $Method VOID .execute(PRIV_VCL, PRIV_TASK, BOOL master=1) Arguments master: when enabled slave servers are not considered for execution. Return value VOID Description Executes a previously enqueued Redis command. When more than one Redis server is available, the destination server is selected according with ``master`` and with the list of weights + subnet masks provided when calling ``redis.subnets()``. WARNING: allowing execution of commands in slave servers (i.e. ``master == false``) must be carefully used: - When Redis Cluster support is disabled, sending a read-write command to a read-only slave server will result in an error reply. - It's safe to send read-only LUA scripts using ``EVAL`` or ``EVALSHA`` commands to a read-only slave server when Redis Cluster support is disabled. Being a read-only slave server does not block writes in the script cache. - When Redis Cluster support is enabled, sending a read-write command to a slave server will result in a redirection to the right master server. This kind of redirections trigger an internal rediscovery of the cluster topology. The client side won't notice the redirection, but triggering such an expensive operation on every command is a **terrible idea**. - **It's not safe to send read-only LUA scripts using ``EVAL`` or ``EVALSHA`` commands to a slave server when Redis Cluster support is enabled**. Redis Cluster handles ``EVAL`` and ``EVALSHA1`` command as write operations that must be redirected to a master server. Therefore, this would result on a rediscovery of the cluster topology on every command execution. The VMOD internally forces ``master == true`` when Redis Cluster support is enabled and ``EVAL`` or ``EVALSHA`` command are submitted in order to avoid this counterintuitive scenario. $Method VOID .easy_execute(PRIV_VCL vcl_priv, PRIV_TASK task_priv, STRING command, [STRING cmd_arg1], [STRING cmd_arg2], [STRING cmd_arg3], [STRING cmd_arg4], [STRING cmd_arg5], [STRING cmd_arg6], [STRING cmd_arg7], [STRING cmd_arg8], [STRING cmd_arg9], [STRING cmd_arg10], [STRING cmd_arg11], [STRING cmd_arg12], [STRING cmd_arg13], [STRING cmd_arg14], [STRING cmd_arg15], [STRING cmd_arg16], [INT timeout], [INT retries], BOOL master = 1 ) Arguments The command argument is mandatory, followed with up to 16 arguments, optionally ending with ``timeout`` (as passed to ``.timeout()``) and/or ``retries`` (as passed to ``.retries()``) and/or ``master`` (``.execute()``). For example: ``db.easy_command("set", "foo", "hello", retries=3, master=true);`` Return value VOID Description Equivalent to calling, ``.command()``, ``.push()`` (possibly multiple times), ``.timeout()``, ``.retries()`` then finally ``.execute()`` using a single command. $Method BOOL .replied(PRIV_TASK) Return value TRUE if a previously executed Redis command using ``.execute()`` returned any reply. Not returning a reply usually means a failed connection, a connection timeout, etc. $Method BOOL .reply_is_error(PRIV_TASK) Return value TRUE if a previously executed Redis command using ``.execute()`` returned an error reply. $Method BOOL .reply_is_nil(PRIV_TASK) Return value TRUE if a previously executed Redis command using ``.execute()`` returned a nil reply. $Method BOOL .reply_is_status(PRIV_TASK) Return value TRUE if a previously executed Redis command using ``.execute()`` returned a status reply. $Method BOOL .reply_is_integer(PRIV_TASK) Return value TRUE if a previously executed Redis command ``.execute()`` returned an integer reply. $Method BOOL .reply_is_boolean(PRIV_TASK) Return value TRUE if a previously executed Redis command ``.execute()`` returned an boolean reply. $Method BOOL .reply_is_double(PRIV_TASK) Return value TRUE if a previously executed Redis command ``.execute()`` returned an double reply. $Method BOOL .reply_is_string(PRIV_TASK) Return value TRUE if a previously executed Redis command ``.execute()`` returned a string or verbatim reply. $Method BOOL .reply_is_array(PRIV_TASK) Return value TRUE if a previously executed Redis command using ``.execute()`` returned an array, map or set reply. $Method STRING .get_reply(PRIV_TASK) Return value A string representation of the reply of a previously executed Redis command using ``.execute()``. Description Do not use this function to access to array, map or set replies. $Method STRING .get_error_reply(PRIV_TASK) Return value If a previously executed Redis command using ``.execute()`` returned an error reply, this function returns a string representation of that reply. $Method STRING .get_status_reply(PRIV_TASK) Return value If a previously executed Redis command using ``.execute()`` returned a status reply, this function returns a string representation of that reply. $Method INT .get_integer_reply(PRIV_TASK) Return value If a previously executed Redis command using ``.execute()`` returned an integer reply, this function returns an integer representation of that reply. $Method BOOL .get_boolean_reply(PRIV_TASK) Return value If a previously executed Redis command using ``.execute()`` returned an boolean reply, this function returns an boolean representation of that reply. $Method REAL .get_double_reply(PRIV_TASK) Return value If a previously executed Redis command using ``.execute()`` returned an double reply, this function returns an double representation of that reply. $Method STRING .get_string_reply(PRIV_TASK) Return value If a previously executed Redis command using ``.execute()`` returned a string or verbatim reply, this function returns a string representation of that reply. $Method INT .get_array_reply_length(PRIV_TASK) Return value If a previously executed Redis command using ``.execute()`` returned an array, map or set reply, this function returns the number of elements in that reply. $Method BOOL .array_reply_is_error(PRIV_TASK, INT index) Arguments index: index in the array reply. Return value If a previously executed Redis command using ``.execute()`` returned an array, map or set reply, this function returns TRUE if the nth element in that reply is an error reply (nested responses are not supported). $Method BOOL .array_reply_is_nil(PRIV_TASK, INT index) Arguments index: index in the array reply. Return value If a previously executed Redis command using ``.execute()`` returned an array, map or set reply, this function returns TRUE if the nth element in that reply is a nil reply (nested responses are not supported). $Method BOOL .array_reply_is_status(PRIV_TASK, INT index) Arguments index: index in the array reply. Return value If a previously executed Redis command using ``.execute()`` returned an array, map or set reply, this function returns TRUE if the nth element in that reply is a status reply (nested responses are not supported). $Method BOOL .array_reply_is_integer(PRIV_TASK, INT index) Arguments index: index in the array reply. Return value If a previously executed Redis command using ``.execute()`` returned an array, map or set reply, this function returns TRUE if the nth element in that reply is an integer reply (nested responses are not supported). $Method BOOL .array_reply_is_boolean(PRIV_TASK, INT index) Arguments index: index in the array reply. Return value If a previously executed Redis command using ``.execute()`` returned an array, map or set reply, this function returns TRUE if the nth element in that reply is an boolean reply (nested responses are not supported). $Method BOOL .array_reply_is_double(PRIV_TASK, INT index) Arguments index: index in the array reply. Return value If a previously executed Redis command using ``.execute()`` returned an array, map or set reply, this function returns TRUE if the nth element in that reply is an double reply (nested responses are not supported). $Method BOOL .array_reply_is_string(PRIV_TASK, INT index) Arguments index: index in the array reply. Return value If a previously executed Redis command using ``.execute()`` returned an array, map or set reply, this function returns TRUE if the nth element in that reply is a string or verbatim reply (nested responses are not supported). $Method BOOL .array_reply_is_array(PRIV_TASK, INT index) Arguments index: index in the array reply. Return value If a previously executed Redis command using ``.execute()`` returned an array, map or set reply, this function returns TRUE if the nth element in that reply is an array, map or set reply (nested responses are not supported). $Method STRING .get_array_reply_value(PRIV_TASK, INT index) Arguments index: index in the array reply. Return value If a previously executed Redis command using ``.execute()`` returned an array, map or set reply, this function returns a string representation of the nth element in that reply (nested responses are not supported). $Method VOID .free(PRIV_TASK) Description Frees memory internally used by Redis commands an replies. It's recommended to use this function, but if not called this will be handled automatically during the next call to ``.command()`` using the same object. $Method STRING .stats( ENUM { json, prometheus } format="json", BOOL stream=0, STRING prometheus_name_prefix="vmod_redis_", BOOL prometheus_default_labels=1, STRING prometheus_extra_labels="") Arguments format: format of the output string. stream: if enabled, the response object will be streamed as a synthetic response. prometheus_name_prefix: prefix to be used in all Prometheus metric names. It's used as a raw value; no validations or transformations at all. prometheus_default_labels: if enabled, some default Prometheus labels will be added to all stats. prometheus_extra_labels: extra Prometheus labels to be added to all stats. It's used as a raw value; no validations or transformations at all. Description Returns internal stats represented as a string. If called during ``vcl_synth`` or ``vcl_backend_error`` with the ``stream`` argument enabled, this function will return an empty string and behave as a call to the ``synthetic`` VCL function with the response object as input. This highly reduces the amount of required workspace memory. $Method INT .counter(STRING name) Arguments name: name of the counter. Description Returns internal counter.